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 Date
object to use that time zone. You're still using the same implementation of Date#toString()
, which formats the Date
object using the default timezone.
您使用特定时区解析日期字符串这一事实不会使打印Date
对象使用该时区。您仍在使用 的相同实现Date#toString()
,它Date
使用默认时区格式化对象。
What you would need is to format
your Date
object with that SimpleDateFormat
object. And if you have that specific string, then you would need another SimpleDateFormat
object 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 Date
doesn't have the concept of TimeZone associated with it. You can only format a Date
object using a specified timezone, and get a string. Or else, switch to JodaTime library.
JavaDate
没有与之关联的 TimeZone 概念。您只能Date
使用指定的时区格式化对象,并获取字符串。否则,切换到JodaTime 库。
回答by Powerlord
Date
is 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
/ SimpleDateFormat
for that TimeZone
and format
it 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 toString
applies 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