将 Long 转换为 Time 时出现问题科特林安卓

问题描述

大家好。我有一个关于天气的项目。而且我面临转换问题,我将日出和日落转换为 Long(秒),我需要转换为 HH:mm。当我运行应用程序时,我得到无效数据,日出:23:30 和日落:14:42。虽然实际上我们在 5:30 日出,20:42 日落。自从我们住在 UTC +6 时区以来,我可以看到 6 小时的差异,这可能相关吗?如何正确转换?我的变换函数

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

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

}

主要活动代码

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()} %"
}

解决方法

java.time

考虑使用 java.time(现代 Java 日期和时间 API)来处理您的时间工作。很抱歉我只能写Java。我首先为您想要的时间格式定义一个格式化程序:

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

格式包括转换为您的时区。如果不是亚洲/乌鲁木齐,请替换正确的时区 ID。

    // 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);

输出为:

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

我还打印了我使用的 Instant 对象。这些以 UTC 打印,您可以识别 23:30 和 14:42 的无效时间。转换为您的时区后,时间是正确的。

您的天气数据还可能包含有关 UTC 偏移量的信息,您可以使用这些信息来代替自己定义时区。你可以检查一下。一个例子:

    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

我只打印偏移量以确认我已正确解释了数字 21600。再次打印预期的日出时间 05:30。日落也是如此,你可能已经猜到了。

问题:java.time 不需要 Android API 级别 26 吗?

java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,内置了现代 API。
  • 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
  • 在较旧的 Android 上,使用脱糖或 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。在后一种情况下,请确保使用子包从 org.threeten.bp 导入日期和时间类。

链接