Showing correct sunrise/sunset times using unix timestamp
Asked Answered
B

2

0

I'm getting a UNIX timestamp from DarkSkyApi for the sunrise & sunset times for the selected location and i want to convert it to a DateTime format and display it to the user. I want the time values to be local.

Example case : The user is in Italy and selects "Tokyo, JP" as the desired location to fetch weather info for. The sunrise & sunset time values should be formatted & shown as local times. So for Tokyo, sunrise should be something around 4:34 AM & 18:36 PM for sunset.

With what i have right now, i'm getting wrong values such as 12:17 for sunrise & 2:29 for sunset. Any ideas on what i'm doing wrong here?

P.S. The tmz var is the timezone of the selected location , so in this case it would be "Asia/Tokyo". Here's what i'm doing right now for the sunset time (same for the sunrise time):

private fun setViewHolderWeekDaySunsetTime(holder: ViewHolder, sunsetTime: Long, tmz: String) {
    val dt = Instant.ofEpochSecond(sunsetTime).atZone(
        ZoneId.of(tmz)
    )
    val formatted = dt.format(DateTimeFormatter.ofPattern("HH:mm"))
    holder.weekDaySunsetTime.text = formatted
}
Bracer answered 7/5, 2020 at 17:22 Comment(7)
You are not using the unix timestamp, but multiply it with 1000. So you are dateformatting a date 50000 years or so in the future. log dt to seeRajput
@FrankNeblung shouldn't i multiply it by 1000 to get the epoch time in millis?Bracer
You can check the meaning of unix timestamps online here. Convert System.currentTimeMillis online hereRajput
@FrankNeblung If i don't multiply the unix timestamp by 1000 i get this unix time = 1588930440 sunset time = 1970-01-19T11:22:10.440+02:00[Europe/Athens] . When i do multiply it i get this : unix time = 1588930440 sunset time = 2020-05-08T12:34+03:00[Europe/Athens] using this Log statement Log.i("WEEKLYWEATHER","unix time = $sunsetTime sunset time = $dt")Bracer
should be formatted & shown as local times - this is the kind of woolly thinking that leads to problems with timezones. Local to where - the user (in Italy) or to the sunset (in Japan)? And why haven't you shown the actual values of sunsetTime, tmz or holder?Solution
@Solution Local to the city from which the data is fetched. E.g. if I'm fetching data from Japan the sunset should be something like 18:45 . Tmz like i mentioned is the tmz of the city always.Bracer
And does the time difference between the local and sunset zones match the difference in your results? There's some information in the comments, but it doesn't seem to match the code in the question, which was edited later ...Solution
A
0

it sounds like the api is returning different time zones depending on what city you request data

So taking that into consideration, when converting the timestamp to a datetime object, you need to do something like this:

import java.time.*

val dt = Instant.ofEpochSecond(/*put time value here*/)
                .atZone(/*put time zone here*/)
                .toLocalDateTime() //this will convert it to your system's date time
Aim answered 8/5, 2020 at 20:35 Comment(3)
This still returns unix time = 1588930440 sunset time = 2020-05-08T12:34 using val dt = Instant.ofEpochSecond(sunsetTime).atZone( ZoneId.of(tmz) ).toLocalDateTime() instead of 2020-05-08T20:23Bracer
ok, I'm not familiar with dark sky API. I'm wondering if the timestamp is in UTC no matter where the location is and then they just give you the timezone as a courtesy. So try setting timezone to UTC and see what happens .atZone(ZoneId.of("UTC"))Aim
It's now returning unix time = 1588930440 sunset time = 2020-05-08T09:34. From the dark sky api doc : "time : The UNIX time at which this data point begins. Daily data point (what i'm using) are always aligned to midnight of the day, all according to the local time zone." and Timezone : "timezone (e.g. America/New_York) required The IANA timezone name for the requested location. "Bracer
P
0

Use this function to find timezone of every place you want with its latitude and longitude:

fun timezonecalculator(latitude:Double,longitude:Double):Double {
    val resultTimeZone = TimezoneMapper.latLngToTimezoneString(latitude, longitude)
    var tz= TimeZone.getTimeZone(resultTimeZone).getDisplayName(
        TimeZone.getTimeZone(resultTimeZone).inDaylightTime(Date()), TimeZone.SHORT)
    if ((tz=="GMT")||(tz=="UTC")||(tz=="WET"))
        tz+="+00:00"
    if ((tz=="CST")||(tz=="MDT"))
        tz+="-06:00"
    if (tz=="AST")
        tz+="-04:00"
    if ((tz=="EST")||(tz=="CDT"))
        tz+="-05:00"
    if (tz=="MST")
        tz+="+05:00"
    if ((tz=="CET")||(tz=="BST"))
        tz+="+01:00"
    if (tz=="EET")
        tz+="+02:00"
    if (tz=="CEST")
    {tz+="+02:00"
        tz=tz.drop(1)}
    if (tz=="PDT")
        tz+="-07:00"
    if (tz=="EDT")
        tz+="-04:00"
    if (tz=="EEST")
    {tz+="+03:00"
    tz=tz.drop(1)}
    if (tz=="WEST")
    {tz+="+01:00"
        tz=tz.drop(1)}
    var sign=tz[3]
    tz=tz.drop(4)
    val minute=tz.drop(3)
    val hour=tz.dropLast(3)
    val min=Integer.parseInt(minute)
    val hou=Integer.parseInt(hour)
    var timezone=hou+(min.toDouble()/60)
    if (sign=='-')
        timezone*=-1
    return timezone
}

And TimeZoneMapper class is https://raw.githubusercontent.com/drtimcooper/LatLongToTimezone/master/src/main/java/com/skedgo/converter/TimezoneMapper.java

See here to know how to use this class: https://github.com/drtimcooper/LatLongToTimezone

You invoke it this way: timezonecalculator(latitude, longitude)

Example: timezonecalculator(36.2, 59.6) Output: 4.5

Piecrust answered 19/5, 2020 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.