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
}
Stelios Papamichail
  • 955
  • 2
  • 19
  • 57
  • 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 see – Frank Neblung May 08 '20 at 06:17
  • @FrankNeblung shouldn't i multiply it by 1000 to get the epoch time in millis? – Stelios Papamichail May 08 '20 at 09:27
  • You can check the meaning of unix timestamps online [here](https://www.unixtimestamp.com/index.php). Convert System.currentTimeMillis online [here](https://currentmillis.com/) – Frank Neblung May 08 '20 at 09:52
  • @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")` – Stelios Papamichail May 08 '20 at 20:22
  • _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`? – Useless May 20 '20 at 21:52
  • @Useless 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. – Stelios Papamichail May 20 '20 at 21:59
  • 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 ... – Useless May 20 '20 at 22:03

2 Answers2

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
MobileMon
  • 8,341
  • 5
  • 56
  • 75
  • 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:23` – Stelios Papamichail May 08 '20 at 21:07
  • 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")) – MobileMon May 08 '20 at 21:11
  • 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. " – Stelios Papamichail May 08 '20 at 21:18
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

MMG
  • 3,226
  • 5
  • 16
  • 43