【问题标题】:Midnight Time zone conversion午夜时区转换
【发布时间】:2021-01-13 15:16:24
【问题描述】:

我正在尝试将一个时区的午夜转换为另一个时区的午夜。 Kotlin 几乎可以轻松转换时区,但在将日期和时间转换为毫秒时,它的工作方式并不相同。

问题:

Indian Time: Mon Sep 28 00:00:00 GMT+5:30 2020
Vancouver Time: Sunday Sep 27 11:30:00 GMT-7:00 2020 

我需要什么

Indian Time: Mon Sep 28 00:00:00 GMT+5:30 2020
Vancouver Time: Sunday Sep 27 11:30:00 GMT-7:00 2020 

这是我尝试过的:

                val today = DateTime().withTimeAtStartOfDay().toDate() //current date and time converted to Date format
                val dateOutputFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss") // formatting the output as SimpleDateFormat

                dateOutputFormat.setTimeZone(TimeZone.getTimeZone("America/Vancouver")) //Setting the timezone
                Log.d("Datey2", "Before conversion ${today}") // Before conversion Mon Sep 28 00:00:00 GMT+5:30 2020

                val Vancouver = Date(dateOutputFormat.format(today)).time //formatting the timezone
                Log.d("Datey2", "After conversion $Vancouver") // After conversion Sun Sep 27 11:30:00 GMT+05:30 2020

                val VancouverMnight = DateTime(Vancouver).withTimeAtStartOfDay().millis
                Log.d("Datey2", "MidNight $VancouverMnight") // MidNight Sun Sep 27 00:00:00 GMT+05:30 2020

输出:

Before conversion Mon Sep 28 00:00:00 GMT+5:30 2020
After conversion Sun Sep 27 11:30:00 GMT+05:30 2020 // Note the GMT+5:30 in vacouver time
MidNight Sun Sep 27 00:00:00 GMT+05:30 2020

然后我将这些转换为毫秒,如下所示

Log.d("Datey2", "After conversion {$VancouverMnight.time}") // using time function gives output in milliseconds

但是当我将温哥华输出转换为毫秒时,我得到以下信息:

1601186400000 // Sep 26 23:00:00 2020 - Goes 2 days before the given time
1601145000000 // Sep 26 11:30:00 2020

我需要什么:

Sep 27 11:30:00 2020
Sep 27 00:00:00 2020 (I need these in milliseconds)

【问题讨论】:

  • 我发现很难准确理解您想要什么,这就是我投反对票的原因。
  • 嗨@OleV.V。非常感谢您阅读本文。我非常感谢投票,并感谢您对原因发表评论。我尽力提出这个问题。但是现在,有人编辑了它:)

标签: android kotlin timezone date-conversion android-date


【解决方案1】:

由于您使用的是 Joda-Time,我建议您要么坚持下去,要么继续使用现代 Java 日期和时间 API 的 java.time。远离DateSimpleDateFormat。它们的设计很差,而且已经过时了,你绝对没有理由去碰它们。

对于 Java 中的 Joda-Time 解决方案,因为这是我可以编写和运行的:

    DateTimeZone vancouverTimeZone = DateTimeZone.forID("America/Vancouver");
    
    DateTimeFormatter dateOutputFormat = DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss")
            .withZone(vancouverTimeZone);
    
    DateTime today = new DateTime().withTimeAtStartOfDay();
    System.out.println("Today: " + today);
    System.out.println("Today as seen in Vancouver: " + today.toString(dateOutputFormat));
    
    long millisBeforeConversion = today.getMillis();
    System.out.println("Millis before conversion: " + millisBeforeConversion);
    
    DateTime vancouverMidnight = today.withZone(vancouverTimeZone)
            .withTimeAtStartOfDay();
    long millisAfterConversion = vancouverMidnight.getMillis();
    System.out.println("Millis after conversion: " + millisAfterConversion);

今天在亚洲/加尔各答时区运行时的输出:

Today: 2020-09-29T00:00:00.000+05:30
Today as seen in Vancouver: 2020/09/28 11:30:00
Millis before conversion: 1601317800000
Millis after conversion: 1601276400000

距您提出问题已过去一天,因此您无法将我输出的毫秒值与您自己的问题进行比较,但您可以验证它们是否与您今天想要的一致(印度已于 9 月 29 日)。

请注意,自纪元以来的毫秒数与时区无关。因此,无论您获得转换为美国/温哥华时区之前还是之后的毫秒数都没有区别。

如果您想继续使用 java.time,请遵循 Arvind Kumar Avinash 的好回答。

【讨论】:

  • 您好,非常感谢您的回答。我可以清楚地看到你的输出和我的输出之间的差异,以及 Arvind 对时间的解释是如何从 Unix 纪元计算出来的,适合这种情况。没错,在 Java 8 之前,Java 中的日期和时间是混乱的。我在某处读到推荐使用 joda time。所以我继续这样做。我将尝试使用 arvind 提到的现代日期和时间。如果这不起作用,我会将其标记为答案。
  • 如果你可以切换到 java.time,我支持你,这是一个很棒的 AP​​I。如果您遇到疑问,请尝试跟进或提出新问题,也许可以使用此处评论中的链接。我相信 Arvind 和我自己都会并且可以帮助您。
【解决方案2】:

问题是您试图直接编写java.util.Date 对象,该对象输出java.util.Date#toString 的值。请注意,日期时间对象应该存储有关日期、时间、时区等的信息,而不是有关格式的信息。 java.util.Date 对象不是像 modern date-time classes 这样的真实日期时间对象;相反,它表示从 1970 年 1 月 1 日的纪元开始的毫秒数。当您打印 java.util.Date 的对象时,其 toString 方法会返回根据该毫秒值计算的日期时间。由于java.util.Date 没有时区信息,它会应用您的JVM 的时区并显示相同的信息。如果您需要在不同的时区打印日期时间,则需要将时区设置为 SimpleDateFormat 并从中获取格式化字符串,例如

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ssZ z");
        Date date = new Date();

        // Date and time in India
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
        // Output to be written to the log file
        System.out.println(sdf.format(date));

        // Date and time in Vancouver
        sdf.setTimeZone(TimeZone.getTimeZone("America/Vancouver"));
        // Output to be written to the log file
        System.out.println(sdf.format(date));
    }
}

输出:

2020/09/29 17:57:06+0530 IST
2020/09/29 05:27:06-0700 GMT-07:00

我建议您从过时且容易出错的 java.util 日期时间 API 和 SimpleDateFormat 切换到 modern java.time 日期时间 API 和相应的格式化 API(包,java.time.format)。从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。如果您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

使用现代日期时间 API:

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ssZ z");

        // Date and time in India
        ZonedDateTime zdtNowIST = LocalDate.now().atStartOfDay((ZoneId.of("Asia/Calcutta")));
        // Output in the default format
        System.out.println(zdtNowIST);
        // Output in the custom format
        System.out.println(zdtNowIST.format(dtf));

        // Date and time in Vancouver
        ZonedDateTime zdtNowVancouver = zdtNowIST.withZoneSameInstant(ZoneId.of("America/Vancouver"));
        // Output in the default format
        System.out.println(zdtNowVancouver);
        // Output in the custom format
        System.out.println(zdtNowVancouver.format(dtf));
    }
}

输出:

2020-09-29T00:00+05:30[Asia/Calcutta]
2020/09/29 00:00:00+0530 IST
2020-09-28T11:30-07:00[America/Vancouver]
2020/09/28 11:30:00-0700 GMT-07:00

我不了解 Kotlin,但我相信您应该能够直接在 Kotlin 中使用 Java 代码。如果没有,至少您应该能够使用 Kotlin 语法对其进行转换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    相关资源
    最近更新 更多