UTC日期解析Java中的不一致 [英] UTC date parsing inconsistency in Java
问题描述
UTC / GMT
日期时,奇怪的是发生了。我将日期格式设置为 yyyy-MM-dd'T'HH:mm:ss'Z
其中 Z
用于 UTC
。我给出以下日期字符串来解析:
String startTimestampString =2013-10-02T00:00:00Z;
我希望得到与输出相同的日期,而是显示
2013-10-01 17:00:00.0
现在确定这个7小时滞后的地方?
代码:
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class DateTest {
public static void main(String [] args)throws ParseException {
SimpleDateFormat date = new SimpleDateFormat(yyyy-MM-dd T'HH:mm:ss'Z);
date.setTimeZone(TimeZone.getTimeZone(UTC));
System.out.println(TimeZone.getTimeZone(UTC)。toString());
String startTimestampString =2013-10-02T00:00:00Z;
long startTimestamp = date.parse(startTimestampString).getTime();
System.out.println(String.format(Long%d and timestamp%s,startTimestamp,new Timestamp(startTimestamp).toString()));
}
}
输出: p>
sun.util.calendar.ZoneInfo [id =UTC,offset = 0,dstSavings = 0,useDaylight = false,transitions = 0,lastRule = null]
长1380672000000和时间戳2013-10-01 17:00:00.0 //错误时间戳应该是2013-10-02 00:00:00.0
java.util.Date没有时区
正如评论所述,您的问题不是理解java.util.Date工作的混乱方式。
A
日期
对象没有时区,但 em>有一个,因为它的toString
方法在生成文本表示(返回的String)时应用您的JVM的默认时区。
Java团队的这种糟糕的设计选择引起了如此多的混乱,包括StackOverflow上的无数类似问题。
日期不是字符串
这里的一个关键思想是,由 toString
方法是一个全新的对象。该字符串不是日期。该字符串是从您的默认时区看到的历史中那一刻的特定表示。历史上的同一时刻,从巴黎或蒙特利尔或加尔各答时区可以看出是两种不同的时间价值。
避免使用java.util.Date
不要浪费你的时间与java.util.Date和.Calendar和SimpleDateFormat。他们是臭名昭着的麻烦。使用 Joda-Time 或新的 java.time包在 Java 8 (灵感来自Joda-Time)。
Joda-Time
Joda-Time 2.3中的示例代码。您的格式符合标准 ISO 8601 格式。 Joda-Time使用ISO 8601作为其默认值,因此在您的情况下不需要解析器/格式化程序。 Joda-Time自动使用内置格式化程序来解析符合ISO 8601的字符串。
String input =2013-10-02T00: 00:00Z;
DateTimeZone timeZoneParis = DateTimeZone.forID(Europe / Paris);
DateTime dateTimeParis = new DateTime(input,timeZoneParis);
DateTimedateTimeMontréal= dateTimeParis.withZone(DateTimeZone.forID(America / Montreal));
DateTime dateTimeIndia = dateTimeParis.withZone(DateTimeZone.forID(Asia / Kolkata));
DateTime dateTimeUtc = dateTimeParis.withZone(DateTimeZone.UTC);
DateTimeFormatter formatter = DateTimeFormat.forStyle(FF).withLocale(Locale.CANADA_FRENCH);
转储到控制台...
System.out.println(dateTimeParis:+ dateTimeParis);
System.out.println(dateTimeMontréal:+dateTimeMontréal);
System.out.println(dateTimeMontréalformatted:+ formatter.print(dateTimeMontréal));
System.out.println(dateTimeIndia:+ dateTimeIndia);
System.out.println(dateTimeUtc:+ dateTimeUtc);
运行时
dateTimeParis:2013-10-02T02:00:00.000 + 02:00
dateTimeMontréal:2013-10-01T20:00:00.000-04:00
dateTimeMontréal格式:mardi 1 octobre 2013 20 h 00 EDT
dateTimeIndia:2013-10-02T05:30:00.000 + 05:30
dateTimeUtc:2013-10-02T00:00:00.000Z
Something weird is happening while parsing a UTC/GMT
date. I set the date format as
"yyyy-MM-dd'T'HH:mm:ss'Z'"
where Z
is for UTC
. And I give following date string to parse:
String startTimestampString = "2013-10-02T00:00:00Z";
I hope to get same date as output but instead it shows
2013-10-01 17:00:00.0
Now sure from where this 7 hour lag coming from?
Code:
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class DateTest {
public static void main(String[] args) throws ParseException {
SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
date.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(TimeZone.getTimeZone("UTC").toString());
String startTimestampString = "2013-10-02T00:00:00Z";
long startTimestamp = date.parse(startTimestampString).getTime();
System.out.println(String.format("Long %d and timestamp %s", startTimestamp, new Timestamp(startTimestamp).toString()));
}
}
Output:
sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Long 1380672000000 and timestamp 2013-10-01 17:00:00.0 // ERROR timestamp should have been 2013-10-02 00:00:00.0
java.util.Date Has No Time Zone
As the comments said, your problem is not understanding the confusing way in which java.util.Date works.
A
Date
object has no time zone, but seems to have one because itstoString
method applies your JVM's default time zone when generating the textual representation (the String being returned).
This poor design choice by the Java team has caused so much confusion, including countless similar Questions on StackOverflow.
The Date Is Not The String
A key idea here is that the String generated by the toString
method is an entirely new object. This string is not the Date. The string is a particular representation of that moment in history as seen from you default time zone. The same moment in history appears as two different time-of-day values when seen from the Paris or Montréal or Kolkata time zones.
Avoid java.util.Date
Do not waste your time with java.util.Date and .Calendar and SimpleDateFormat. They are notoriously troublesome. Use Joda-Time or new java.time package in Java 8 (inspired by Joda-Time).
Joda-Time
Example code in Joda-Time 2.3. Your format is in the standard ISO 8601 format. Joda-Time uses ISO 8601 as its defaults, so no need for parsers/formatters in your case. Joda–Time automatically uses built-in formatters to parse ISO 8601 compliant strings.
String input = "2013-10-02T00:00:00Z";
DateTimeZone timeZoneParis = DateTimeZone.forID( "Europe/Paris" );
DateTime dateTimeParis = new DateTime( input, timeZoneParis );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );
DateTime dateTimeIndia = dateTimeParis.withZone( DateTimeZone.forID( "Asia/Kolkata" ) );
DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTimeFormatter formatter = DateTimeFormat.forStyle( "FF" ).withLocale( Locale.CANADA_FRENCH );
Dump to console…
System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );
System.out.println( "dateTimeMontréal formatted: " + formatter.print( dateTimeMontréal ) );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
When run…
dateTimeParis: 2013-10-02T02:00:00.000+02:00
dateTimeMontréal: 2013-10-01T20:00:00.000-04:00
dateTimeMontréal formatted: mardi 1 octobre 2013 20 h 00 EDT
dateTimeIndia: 2013-10-02T05:30:00.000+05:30
dateTimeUtc: 2013-10-02T00:00:00.000Z
这篇关于UTC日期解析Java中的不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!