【问题标题】:Displaying time from timestamp in Unix, UTC in Android Kotlin在 Unix 中显示时间戳,在 Android Kotlin 中显示 UTC
【发布时间】:2021-06-28 12:36:21
【问题描述】:

我正在开发一个简单的天气应用程序,并尝试以“K:mm a”格式显示时间(例如上午 6:30)。我正在为用户搜索的指定位置(例如 NYC)获取 Unix、UTC 中的时间戳。时间戳看起来像 1624836905,时区偏移量像 -14400。我有一个函数将两者相加,将其转换为毫秒,并应以指定的格式返回时间。函数如下:

fun dateTime(time: Int, zone: Int, format: String = "EEE, MMMM d K:mm a"): String {
        return try {
            val sdf = SimpleDateFormat(format)
            val netDate = Date((time.plus(zone)).toLong() * 1000)
            sdf.timeZone = TimeZone.getTimeZone("UTC")
            sdf.format(netDate)
        } catch (e: Exception) {
            e.toString()
        }
    }

我称之为:

sunriseTextView.text = dateTime(result2.lookup<Int>("daily.sunrise")[0], timeZone, "K:mm a")
sunsetTextView.text = dateTime(result2.lookup<Int>("current.sunset")[0], timeZone, "K:mm a")

预期输出是日出/日落时间,例如早上 6:01 和晚上 9:05。我也在从 API 获得的指定地点渲染当前时间。如下:

dateView.text = dateTime(result2.lookup<Int>("current.dt")[0], timeZone)

以“EEE, MMMM d K:mm a”格式输出该地点的当前日期和时间(例如,6 月 28 日星期一上午 8:23)。

当前时间总是正确的,但是日出和日落时间有问题。例如,如果我输入 NYC,日出是晚上 7:35,日落是上午 10:39。另一方面,东京的日出和日落在凌晨 4:27 和晚上 7:00 显示是正确的。

显然我遗漏了一些东西,因为我知道 API 数据是正确的。我正在寻找任何建议,但是,如果没有 API 限制,例如需要 API 26 的 kotlinx-datetime,我将不胜感激。

【问题讨论】:

    标签: android date kotlin


    【解决方案1】:

    既然有API Desugaring,你可以在API版本低于26的情况下使用java.time

    这意味着您不必依赖那些过时的日期时间类,例如 java.util.Datejava.text.SimpleDateFormat

    您的fun 可以这样重写:

    fun dateTime(time: Int, zone: String, format: String = "EEE, MMMM d K:mm a"): String {
        // parse the time zone
        val zoneId = ZoneId.of(zone)
        // create a moment in time from the given timestamp (in seconds!)
        val instant = Instant.ofEpochSecond(time.toLong())
        // define a formatter using the given pattern and a Locale
        val formatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH)
        // then make the moment in time consider the zone and return the formatted String
        return instant.atZone(zoneId).format(formatter)
    }
    

    这是一个简单的fun main() 中的一些使用示例:

    fun main() {
        val timestamp: Int = 1624836905 // your example epoch seconds
        // try two different zones
        val newYorkTime = dateTime(timestamp, "America/New_York")
        val tokyoTime = dateTime(timestamp, "Asia/Tokyo")
        // and print the results
        println(newYorkTime)
        println(tokyoTime)
    }
    

    这个例子的输出:

    Sun, June 27 7:35 PM
    Mon, June 28 8:35 AM
    

    请注意,如果您只想提供 UTC 小时的偏移量,也可以使用 offset: Int 而不是 zone: String。您需要调整此fun 的两行然后:

    fun dateTime(time: Int, offset: Int, format: String = "EEE, MMMM d K:mm a"): String {
        // parse the time zone
        val zoneOffset = ZoneOffset.ofHours(offset)
        // create a moment in time from the given timestamp (in seconds!)
        val instant = Instant.ofEpochSecond(time.toLong())
        // define a formatter using the given pattern and a Locale
        val formatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH)
        // then make the moment in time consider the zone and return the formatted String
        return instant.atOffset(zoneOffset).format(formatter)
    }
    

    在这样的主目录中使用它

    fun main() {
        val timestamp: Int = 1624836905
        
        val newYorkTime = dateTime(timestamp, -4)
        val tokyoTime = dateTime(timestamp, 9)
        println(newYorkTime)
        println(tokyoTime)
    }
    

    将产生完全相同的输出。

    此外,DateTimeFormatter 中使用的Locale 也可以作为函数参数,以防您希望支持不同的语言(这会影响月份和星期几的名称)。

    【讨论】:

    • 非常感谢您快速而彻底的回答。我尝试了将时区偏移作为字符串和整数的两个选项。但是,我遇到了同样的问题,即当前时间,日出和日落对于从 UTC 向东的地方是正确的,但是负偏移的地方有错误的时间。如:当前时间,NYC:时区:America/New_York,时间戳:1624892520,时间:周一,6 月 28 日上午 11:02,日出:时间戳:1624836905,时间:7:35 PM,日落:时间戳:1624891150,时间:上午 10:39
    • @Klariskao 你能详细描述一下这个错误吗?我想我不太明白你的情况出了什么问题。 错误的时间是什么意思?是不是上午 10:39 的日落是错误的(看起来)?那么问题就出在你收到的价值上,因为1624891150 绝对是纽约的上午 10:39。
    • 我在下面发表了一条评论,希望能解释这个问题。事实证明,来自 API 的数据不是我所期望的,因此结果也是错误的。感谢您的努力和回答。它可以完美地处理来自不同 API 的数据。
    【解决方案2】:

    我在 Python 中有一个类似的函数:

        def time(self, unix_time, time_zone):
            date = datetime.utcfromtimestamp(unix_time + time_zone)
            return (datetime.strftime(date, '%I:%M %p'))
    

    我这样称呼:

    WeatherApp.time_zone = self.weather_results['timezone_offset']
    print(self.time_date(self.weather_results['current']['dt'], self.time_zone))
    print('Sunrise: ' + self.time(self.weather_results['current']['sunrise'], self.time_zone))
    print('Sunset: ' + self.time(self.weather_results['current']['sunset'], self.time_zone))
    

    我试图在 Kotlin 中获得相同的结果。但是比较输出如下:

    Location: Tokyo, Japan 
    Current time and date: Tue, June 29 06:53 PM (same in Python and Kotlin from Asia/Tokyo, 1624960598 1624961970
    32400)
    Sunrise: 04:27 AM (as outputted in Python from 32400, 1624908462)
    Sunset: 07:00 PM (as outputted in Python from 32400, 1624960847)
    Sunrise: 4:27 AM (as outputted in Kotlin from Asia/Tokyo, 1624908467)
    Sunset: 7:00 PM (as outputted in Kotlin from Asia/Tokyo, 1624960846)
    ---
    Location: New York, United States
    Current time and date: Tue, June 29 6:02 AM  (same in Python and Kotlin from America/New_York, 1624960973)
    Sunrise: 05:27 AM (as outputted in Python from -14400, 1624958860)
    Sunset: 08:31 PM (as outputted in Python from -14400, 1625013070)
    Sunrise: 7:35 PM (as outputted in Kotlin from America/New_York, 1624923330)
    Sunset: 10:39 AM (as outputted in Kotlin from America/New_York, 1624977548)
    

    比较时间戳表明从 API 获得的数据由于某种原因而有所不同。我目前通过使用不同的 API 解决了这个问题。我使用的是 OpenWeather 的 One Call API。我想不出发生这种情况的原因,但是,通过从不同的 API 获取时间戳,问题不再存在。

    【讨论】:

    • 我花了好几天的时间认为这是函数。我完全信任 API XD
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    相关资源
    最近更新 更多