将 CST 时区转换为所需时区 Java

Convert CST time zone to required Time zone Java

我需要将 CST 中的日期转换为所需时区。我将在 CST 时区中获取日期作为字符串,例如“11/5/2018 12:54:20”。我必须将其转换为作为参数传递的时区。假设让我们把它当作 "GMT+0530"。 理想情况下上述日期的结果 "Nov 06 2018 00:24:20"

我尝试了以下代码,它返回传递的日期 (11/05/2018 12:54:20) 相同而不是 (Nov 06 2018 00:24:20) 。我在一个有 IST 时区的系统上执行了这个。

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT-0600"));
    SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT+0530"));
    System.out.println(sdf2.format(sdf.parse("11/5/2018 12:54:20").getTime()));

编辑: 答案:

    DateTimeFormatter f = DateTimeFormatter.ofPattern( "M/d/uuuu HH:mm:ss" ) ;
    LocalDateTime ldt = LocalDateTime.parse( "11/5/2018 12:54:20" , f ) ;
    ZoneId z = ZoneId.of( "GMT-0600" ) ;
    ZonedDateTime zdt = ldt.atZone( z ) ;
    System.out.println(zdt);
    ZoneId zKolkata = ZoneId.of( "GMT+0530" ) ;
    ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata ) ;
    System.out.println(zdtKolkata);

tl;博士

LocalDateTime                                            // Represent a date and a time-of-day, without offset nor zone. So *not* a moment, *not* a point on the timeline.
.parse( 
    "11/5/2018 12:54:20" , 
    DateTimeFormatter.ofPattern( "d/M/uuuu HH:mm:ss" )   // Define a formatting pattern to match your input string.
)                                                        // Returns a `LocalDateTime`.
.atZone(                                                 // Assign a time zone, to give meaning to the `LocalDateTime` object, making it a `ZonedDateTime` object.
    ZoneId.of( "America/New_York" )                      // Define a time zone properly with `Continent/Region` naming, never 2-4 letter pseudo-zones such as CST or IST.
)                                                        // Returns a `ZonedDateTime` object.
.withZoneSameInstant(                                    // Adjust from New York time to Kolkata time. Some moment, different wall-clock time.
    ZoneId.of( "Asia/Kolkata" )
)                                                        // Returns another `ZonedDateTime` object rather than altering (“mutating”) the original, per Immutable Objects pattern.
.toString()                                              // Generate text in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.

2018-05-11T22:24:20+05:30[Asia/Kolkata]

java.time

您正在使用可怕的旧 类,现在被 java.time 类.

取代

将您的输入字符串解析为 LocalDateTime,因为它缺少任何与 UTC 或时区的偏移指示。

定义格式模式以匹配您的输入。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "d/M/uuuu HH:mm:ss" ) ;
LocalDateTime ldt = LocalDateTime.parse( "11/5/2018 12:54:20" , f ) ;

ldt.toString(): 2018-05-11T12:54:20

你说这是为 CST 设计的。您指的是中国标准时间吗?还是北美中部标准时间?

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/CasablancaPacific/Auckland。切勿使用 CSTESTIST 等 2-4 个字母的缩写,因为它们 不是 真实时区,未标准化,也不是甚至是独一无二的(!)。

我假设你指的是纽约时间。

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

zdt.toString(): 2018-05-11T12:54:20-04:00[America/New_York]

显然,您想通过不同地区、不同时区的人们使用的挂钟时间的镜头看到同一时刻。 IST 是指爱尔兰标准时间吗?还是印度标准时间?同样,使用实时区域而不是这些 2-4 个字符的伪区域。

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata ) ;

zdtKolkata.toString(): 2018-05-11T22:24:20+05:30[Asia/Kolkata]

要以 UTC 格式查看同一时刻,请提取 Instant

Instant instant = zdtKolkata.toInstant() ;

instant.toString(): 2018-05-11T16:54:20Z

这三个(zdtzdtKolkatainstant)都代表同一时刻,时间轴上的同一点。

相比之下,ldt作为一个LocalDateTime对象代表一个时刻,是时间轴上的一个点。在您为其分配时区以赋予其上下文之前,它没有任何实际意义。在分配该区域之前,我们不知道在澳大利亚、非洲或美国是指中午时间。它可能意味着大约 26-27 小时中的任何一个,即全球时区范围。

ISO 8601

与其发明自己的格式来将日期时间值作为文本交换,不如使用标准 ISO 8601 格式。

java.time类方便在generating/parsing个字符串时默认使用ISO 8601格式。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

在哪里获取java.time类?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

您将 sdf 的时区设置了两次,而没有设置 sdf2 的时区,因此得到的结果不正确。此外,将对象传递给 DateFormat::format().

时不需要调用 getTime()

这是您的代码的固定版本:

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
TimeZone cstTimeZone = TimeZone.getTimeZone("CST");
sdf.setTimeZone(cstTimeZone);

SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
sdf2.setTimeZone(TimeZone.getTimeZone("GMT+0530"));
System.out.println(sdf2.format(sdf.parse("11/5/2018 12:54:20")));

请注意,您使用的 类 已经很旧了,从版本 8 开始,Java 提供了新的 Date and Time APIs