午夜时区转换

问题描述

我正在尝试将一个时区的午夜转换为另一个时区的午夜。 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)

解决方法

问题是您试图直接编写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的时区并显示相同的时区。如果您需要在其他时区中打印日期时间,则需要将时区设置为SimpleDateFomrat,并从中获取格式化的字符串,例如

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语法进行转换。

,

由于您使用的是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的良好回答。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...