关于日期:将CST时区转换为所需的时区Java

Convert CST time zone to required Time zone Java

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

我已经尝试了下面的代码,它返回了传递日期(11/05/2018 12:54:20)而不是(Nov 06 2018 00:24:20)。 我在具有IST时区的系统上执行了此操作。

1
2
3
4
5
    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()));

编辑:
回答:

1
2
3
4
5
6
7
8
    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;博士

1
2
3
4
5
6
7
8
9
10
11
12
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或时区的指示。

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

1
2
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。你的意思是中国标准时间吗?或北美的中央标准时间?

continent/region的格式指定正确的时区名称,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4字母缩写,例如CSTESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

我会假设你的意思像纽约时代。

1
2
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个字符的伪区域。

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

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

要查看UTC中的相同时刻,请提取Instant

1
Instant instant = zdtKolkata.toInstant() ;

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

所有这三个(zdtzdtKolkataInstant)都代表相同的时刻,即时间轴上的相同点。

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

ISO 8601

不要发明自己的格式来将日期时间值作为文本进行交换,而是使用标准的ISO 8601格式。

在生成/解析字符串时,java.time类在默认情况下方便地使用ISO 8601格式。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。

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

从哪里获取java.time类?

  • Java SE 8,Java SE 9,Java SE 10,Java SE 11及更高版本 - 带有捆绑实现的标准Java API的一部分。

    • Java 9增加了一些小功能和修复。
  • Java SE 6和Java SE 7

    • 大多数java.time功能都被反向移植到Java 6& 7在ThreeTen-Backport。
  • Android的

    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android(<26),ThreeTenABP项目采用ThreeTen-Backport(如上所述)。请参见如何使用ThreeTenABP ....

ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的类,例如IntervalYearWeekYearQuarter等。


您正在设置sdf的时区两次,而不是设置sdf2的时区,从而得到不正确的结果。此外,将对象传递给DateFormat::format()时,无需调用getTime()

以下是您的代码的固定版本:

1
2
3
4
5
6
7
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提供了新的日期和时间API。