0

Hello everybody. I have a project about the weather. And I am facing conversion problem, I am getting sunrise and sunset to Long (seconds) and I need to convert to HH: mm. When I run the application, I get invalid data, sunrise: 23:30 and sunset: 14:42. Although, in fact, we have sunrise at 5:30, sunset at 20:42. I can see a difference of 6 hours since we live in UTC +6 timezone, could this be related? how to convert correctly? my transform function :

fun Long?.format(pattern: String? = "dd/MM/yyyy"): String{
this?.let {
    val sdf = SimpleDateFormat(pattern, Locale.getDefault())

    return sdf.format(Date(this * 1000))
}
return ""

}

mainactivity code

private fun setValuesToViews(it: ForeCast) {
    val tvTemperature = findViewById<TextView>(R.id.tv_temperature)
    val tvDate = findViewById<TextView>(R.id.tv_date)
    val tvTempMax = findViewById<TextView>(R.id.tv_temp_max)
    val tvTempMin = findViewById<TextView>(R.id.tv_temp_min)
    val tvFeelsLike = findViewById<TextView>(R.id.tv_feels_like)
    val tvWeather = findViewById<TextView>(R.id.tv_weather)
    val tvSunrise = findViewById<TextView>(R.id.tv_sunrise)
    val tvSunset = findViewById<TextView>(R.id.tv_sunset)
    val tvHumidity = findViewById<TextView>(R.id.tv_humidity)

    tvTemperature.text = it.current?.temp?.toString()
    tvDate.text = it.current?.date.format()
    tvTempMax.text = it.daily?.get(0)?.temp?.max?.roundToInt()?.toString()
    tvTempMin.text = it.daily?.get(0)?.temp?.min?.roundToInt()?.toString()
    tvFeelsLike.text = it.current?.feels_like?.roundToInt()?.toString()
    tvWeather.text = it.current?.weather?.get(0)?.description
    tvSunrise.text = it.current?.sunrise.format("hh:mm")
    tvSunset.text = it.current?.sunset.format("hh:mm")
    tvHumidity.text = "${it.current?.humidity?.toString()} %"
}
Jyja
  • 11
  • 5
  • Didn't understand what your actual problem is. Just add 6 hours to that long to shift the time 6 hrs later(if that's your actual problem). – Light Yagami Jul 08 '21 at 10:58
  • Try to set the timezone of SimpleDateFormat. something like: sdf.timezone = TimeZone.getTimeZone("UTC"). Hopefully, this will resolve your problem. – imvishi Jul 08 '21 at 11:52
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends. See if you either can use [desugaring](https://developer.android.com/studio/write/java8-support-table) or add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project, in order to use java.time, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Jul 08 '21 at 14:50
  • Does this answer your question? [How do I convert epoch time to date and time zone is defined in offset in millisecond](https://stackoverflow.com/questions/58111614/how-do-i-convert-epoch-time-to-date-and-time-zone-is-defined-in-offset-in-millis) – Ole V.V. Jul 08 '21 at 17:23
  • 1
    @imvishi thanks, this helped me solve the problem. If you write the same thing as an answer, I can mark it as a solution to the problem. – Jyja Jul 09 '21 at 05:06
  • @OleV.V. thanks next time I will definitely try – Jyja Jul 09 '21 at 05:13

1 Answers1

0

java.time

Consider using java.time, the modern Java date and time API, for your time work. I am sorry that I can write only Java. I am first defining a formatter for your desired time format:

private static final DateTimeFormatter TIME_FORMATTER
        = DateTimeFormatter.ofPattern("HH:mm");

Formatting includes conversion to your time zone. Please substitute the correct time zone ID if it didn’t happen to be Asia/Urumqi.

    // Example time zone at offset +06:00
    ZoneId zone = ZoneId.of("Asia/Urumqi");
    
    long sunriseLong = 1_625_700_600;
    long sunsetLong = 1_625_755_320;

    Instant sunrise = Instant.ofEpochSecond(sunriseLong);
    System.out.println(sunrise);
    String sunriseText = sunrise.atZone(zone).format(TIME_FORMATTER);
    System.out.println(sunriseText);
    
    Instant sunset = Instant.ofEpochSecond(sunsetLong);
    System.out.println(sunset);
    String sunsetText = sunset.atZone(zone).format(TIME_FORMATTER);
    System.out.println(sunsetText);

Output is:

2021-07-07T23:30:00Z
05:30
2021-07-08T14:42:00Z
20:42

I have also printed the Instant objects that I use. These print in UTC, and you recognize the invalid times 23:30 and 14:42. After converting to your time zone the times are correct.

Your weather data may also include information about UTC offset that you may use instead of defining the time zone yourself. You could check. An example:

    int timezone = 21600;
    
    ZoneOffset offset = ZoneOffset.ofTotalSeconds(timezone);
    System.out.println(offset);
    String sunriseText = sunrise.atOffset(offset).format(TIME_FORMATTER);
    System.out.println(sunriseText);
+06:00
05:30

I only printed the offset as confirmation that I have interpreted the number, 21600, correctly. The expected sunrise time of 05:30 is printed again. Sunset goes in the same way, as you may have guessed already.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161