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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21939967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:30:58  来源:igfitidea点击:

Java SimpleDateFormat interpret parse-string as UTC

javadate

提问by wutzebaer

my timezone is GMT+1.

我的时区是 GMT+1。

so a "Date"-object with "22.09.1985 00:00UTC" prints "Sun Sep 22 01:00:00 CEST 1985" on the tostring function.

因此,带有“22.09.1985 00:00UTC”的“Date”对象在 tostring 函数上打印“Sun Sep 22 01:00:00 CEST 1985”。

Now i'm trying to create this date by parsing "22/09/1985" with simpleDateFormat

现在我试图通过用 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

how can i configure simpledateformat that it creates an Date which prints "Sun Sep 22 01:00:00 CEST 1985" with input string "22/09/1985"?

我如何配置 simpledateformat 以创建一个日期,该日期打印“Sun Sep 22 01:00:00 CEST 1985”和输入字符串“22/09/1985”?

采纳答案by wutzebaer

My assumption was wrong,

我的假设是错误的,

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

so

所以

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

is exactly what i wanted, the date i compared it with was wrong.

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

回答by Rohit Jain

The fact that you're parsing a date string, using a specific time zone, doesn't make the printed Dateobject to use that time zone. You're still using the same implementation of Date#toString(), which formats the Dateobject using the default timezone.

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

What you would need is to formatyour Dateobject with that SimpleDateFormatobject. And if you have that specific string, then you would need another SimpleDateFormatobject for parsing that string:

你会需要的是formatDate与该对象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 Datedoesn't have the concept of TimeZone associated with it. You can only format a Dateobject using a specified timezone, and get a string. Or else, switch to JodaTime library.

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

回答by Powerlord

Dateis a relatively "dumb" class, as it just represents the number of milliseconds since 1970-01-01 00:00:00 UTC.

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

If you want to print out a Date as if it were a different timezone, you need to construct a DateFormat/ SimpleDateFormatfor that TimeZoneand formatit to a String that way.

如果你想打印出日期,就好像它是一个不同的时区,你需要构建一个DateFormat/SimpleDateFormatTimeZoneformat它把一个字符串的方式。

回答by Basil Bourque

Avoid java.util.Date & Calendar

避免使用 java.util.Date 和 Calendar

You've found one of the many reasons to avoid using java.util.Date & .Calendar. They are notoriously troublesome. Either use Joda-Timeor, in Java 8, the new java.time packagewhich is inspired by Joda-Time and defined by JSR 310.

您已经找到了避免使用 java.util.Date 和 .Calendar 的众多原因之一。他们是出了名的麻烦。要么使用Joda-Time,要么在 Java 8 中使用受 Joda-Time 启发并由JSR 310定义的新java.time 包

Search StackOverflow for "joda date" to find many examples.

在 StackOverflow 中搜索“joda date”以找到许多示例。

Time Zone

时区

You said:

你说:

my timezone is GMT+1.

我的时区是 GMT+1。

Incorrect, your local offsetfrom UTC/GMT is +01. That is not your time zone. A time zone is an offset plusrules about Daylight Saving Time (DST) and other anomalies.

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

And that offset should have two digits: +01(or +01:00) rather than +1, according to the ISO 8601standard.

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

Avoid the 3 or 4 letter codes such as CET. They are neither standardized nor unique. Use proper time zone names.

避免使用 3 或 4 个字母的代码,例如 CET。它们既不标准化也不独特。使用正确的时区名称

Generally speaking, you should specify a time zone in all your date-time work rather than rely on the current JVM's default.

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

In both Joda-Time and java.time, a date-time object truly knows its assigned time zone. A java.util.Date has no time zone, but seems to because its toStringapplies the default time zone when creating a String representation, as you sadly learned the hard way.

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

Example Code

示例代码

Some code using Joda-Time 2.3.

一些使用 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.

Dump to console…

转储到控制台...

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

When run…

运行时…

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