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

时间:2018-11-05 21:37:21

标签: java date simpledateformat

我需要将CST中的日期转换为所需的时区。我将在CST时区中将日期作为字符串形式获取,例如“ 11/5/2018 12:54:20”。我必须将其转换为作为参数传递的时区。假设将其作为“ GMT + 0530”。 上述日期的结果最好是“ 2018年11月6日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);

2 个答案:

答案 0 :(得分:2)

tl; dr

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 [亚洲/加尔各答]

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设计的。您是说中国标准时间吗?还是北美的中部标准时间?

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

我假设你的意思是类似纽约时间。

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

zdt.toString():2018-05-11T12:54:20-04:00 [美国/纽约]

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

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

zdtKolkata.toString():2018-05-11T22:24:20 + 05:30 [亚洲/加尔各答]

要在UTC中查看同一时刻,请提取Instant

Instant instant = zdtKolkata.toInstant() ;
  

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

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

相反,作为ldt对象的LocalDateTime并不表示时刻,是时间线上的一点。在您为其分配时区以提供上下文之前,它没有任何实际意义。在指定该区域之前,我们不知道在澳大利亚,非洲或美国是中午。这可能意味着大约26-27小时(全球时区范围)。

ISO 8601

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

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


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:0)

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

这是您代码的固定版本:

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