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
Java SimpleDateFormat interpret parse-string as UTC
提问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:
你会需要的是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 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/SimpleDateFormat为TimeZone和format它把一个字符串的方式。
回答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

