Java SimpleDateFormat将解析字符串解释为UTC

时间:2014-02-21 16:35:18

标签: java date

我的时区是GMT + 1.

所以“日期”对象与“22.09.1985 00:00UTC”在tostring函数上打印“Sun Sep 22 01:00:00 CEST 1985”。

现在我正试图通过使用simpleDateFormat解析“22/09/1985”来创建这个日期

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getDefault());
Date d = sdf.parse("22/09/1985");
    => Sun Sep 22 00:00:00 CEST 1985

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d = sdf.parse("22/09/1985");
    => Sun Sep 22 02:00:00 CEST 1985

如何配置simpledateformat,它会创建一个Date,用输入字符串“22/09/1985”打印“Sun Sep 22 01:00:00 CEST 1985”?

4 个答案:

答案 0 :(得分:10)

我的假设是错误的,

22.09.1985 00:00UTC is actually 22.09.1985 02:00CET

所以

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d = sdf.parse("22/09/1985");

正是我想要的,我与它比较的日期是错误的。

答案 1 :(得分:4)

避免使用java.util.Date&日历

您已经找到避免使用java.util.Date&的众多原因之一。 。日历。众所周知,它们很麻烦。使用Joda-Time或在Java 8中使用受Joda-Time启发并由java.time package定义的新JSR 310

在StackOverflow中搜索“joda date”以找到很多例子。

时区

你说:

  

我的时区是GMT + 1.

不正确,您从UTC / GMT的本地偏移量是+01。那不是你的时区。时区是关于夏令时(DST)和其他异常的偏移规则。

根据ISO 8601标准,该偏移应该有两位数:+01(或+01:00)而不是+1

避免使用CET等3或4个字母代码。它们既不标准也不独特。使用proper time zone names

一般来说,您应该在所有日期时间工作中指定时区,而不是依赖当前JVM的默认值。

在Joda-Time和java.time中,日期时间对象确实知道其分配的时区。 java.util.Date没有时区,但似乎是因为它的toString在创建String表示时应用了默认时区,因为你遗憾地学到了很难。

示例代码

使用Joda-Time 2.3的一些代码。

String input = "22/09/1985";

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Amsterdam" );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd/MM/yyyy" );
DateTime dateTime = formatter.withZone( timeZone ).parseDateTime( input );
DateTime dateTimeUtcGmt = dateTime.withZone( DateTimeZone.UTC );
DateTime dateTimeIndia = dateTime.withZone( DateTimeZone.forID( "Asia/Kolkata" ) );
String outputMontreal = DateTimeFormat.forStyle( "FF" ).withZone( DateTimeZone.forID( "America/Montreal" ) ).withLocale( Locale.CANADA_FRENCH ).print( dateTime );
// All of the above date-time represent the very same moment in the timeline of the Universe.

转储到控制台...

System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTimeUtcGmt: " + dateTimeUtcGmt );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "outputMontreal: " + outputMontreal );

跑步时......

dateTime: 1985-09-22T00:00:00.000+02:00
dateTimeUtcGmt: 1985-09-21T22:00:00.000Z
dateTimeIndia: 1985-09-22T03:30:00.000+05:30
outputMontreal: samedi 21 septembre 1985 18 h 00 EDT

答案 2 :(得分:3)

使用特定时区解析日期字符串的事实不会使打印的Date对象使用该时区。您仍在使用Date#toString()的相同实现,它使用默认时区格式化Date对象。

您需要的是format Date对象与SimpleDateFormat对象。如果你有那个特定的字符串,那么你需要另一个SimpleDateFormat对象来解析该字符串:

String dateString = "22/09/1985";

SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy");
Date parsedDate = parser.parse(dateString);

SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(formatter.format(parsedDate));

Java Date没有与之关联的TimeZone概念。您只能使用指定的时区格式化Date对象,并获取字符串。或者,切换到JodaTime library

答案 3 :(得分:1)

Date是一个相对“哑”的类,因为它只代表自1970-01-01 00:00:00 UTC以来的毫秒数。

如果您想打印一个日期,就好像它是一个不同的时区,您需要为DateFormatformat构建一个SimpleDateFormat / TimeZone这样的字符串。