决定要求这一点,因为我无法找到StackOverflow的一个类似的例子。
我想分析使用SimpleDateFormat的日期字符串和时区。 我(希望)我仔细阅读文档,并写了这个程序,重复的问题。
import java.text.DateFormat;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class SDF {
private static final String FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
public static void main(String[] args) throws ParseException {
DateFormat formatter = new SimpleDateFormat(FORMAT, Locale.ENGLISH);
formatter.setLenient(false);
String dateString = args[0];
System.out.println(" Format: " + FORMAT);
Date date = formatter.parse(dateString);
System.out.println(" Parsed time in millis: " + date.getTime());
System.out.println(" Parsed timezone: " + formatter.getTimeZone().getDisplayName());
System.out.println(" Parsed offset: " + formatter.getTimeZone().getRawOffset() / 1000 / 60 / 60 + "hrs.");
}
}
如果我使用“EDT”或在我的输入字符串任何其他支持时区标志,然后调用getTimeZone获取()在DateFormat对象上返回正确的时区和原始的GMT偏移量。
$ java SDF "Thu, 1 Jan 2015 00:00:00 EDT"
Parsed time in millis: 1420084800000
Parsed timezone: Eastern Standard Time
Parsed offset: -5hrs.
$ java SDF "Thu, 1 Jan 2015 00:00:00 PST"
Parsed time in millis: 1420099200000
Parsed timezone: Pacific Standard Time
Parsed offset: -8hrs.
然而,当我使用+0000符号,日期millisconds返回正确的,因为在UTC纪元的时间,但该时区始终默认为我的本地时区。
$ java SDF "Thu, 1 Jan 2015 00:00:00 +0000"
Parsed time in millis: 1420070400000
Parsed timezone: Central European Time
Parsed offset: 1hrs.
$ java SDF "Thu, 1 Jan 2015 00:00:00 -0800"
Parsed time in millis: 1420099200000
Parsed timezone: Central European Time
Parsed offset: 1hrs.
这是否意味着我只能在输入字符串使用“EDT”,“BST”还是我误用SimpleDateFormat的API?
当使用时区说明符,如“+0000”和“-0800”,DateFormat类将解析日期字符串,尊重ZoneOffset,因为你已经通过比较,因为时代的米利斯证明。 然而,日期格式的内部时区不会被改变!
现在,这里是奇数位。 如果您使用的时区修饰符如GMT或PST,这将在实际的DateFormat的内部时区改变。 这是由我的程序演示了,但我不知道这点是什么。 我相信你是期待DateFormat对象,以反映“最后的解析”日期的时区滥用API,但您的代码以及矿山节目,这是情况并非如此。 事实上, Java文档的DateFormat.parse()
没有提及该怎么办TimeZone
的格式会改变,所以我们不应该依赖这个“功能”。
事实上,如果我们检查上可用的API Date
对象,我们发现的时区支持是真的很差。 注意:在我的程序, Date.toString()
给出了相同的输出,无论解析输入字符串。 Java的通过自嘲的认识到这一点很早就Date.getTimezoneOffset()
在Java 1.1的方法。 得出的结论是, Date
对象只表示从时代米利斯-无时区支持!
这种古怪的行为,以及其他许多这样的例子,这就是为什么你应该避免Java 7的日期和时间处理类。 从对Java 7的日期甲骨文网站:
一些日期和时间类[Java中7]也表现出相当差的API设计。
如果你能使用Java 8,你会发现类的行为java.time
包更好的设计。 我已经在我的程序给出一个例子。 如果你不能移动到Java 8,然后乔达时间是要走的路。 下面有说明如何解析,甚至后,时区信息被记住和尊敬的一个Java 8例。 乔达时间的作品一样好,而这些方法的执行将避免你在这里面临的问题。
我的程序:
package com.company;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
public class Main {
private static final String FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
public static void main(String[] args) throws ParseException {
DateFormat formatter = new SimpleDateFormat(FORMAT, Locale.ENGLISH);
formatter.setLenient(false);
String dateString = "Thu, 1 Jan 2015 00:00:00 EDT";
String dateString2 = "Thu, 1 Jan 2015 00:00:00 PST";
String dateString3 = "Thu, 1 Jan 2015 00:00:00 +0000";
String dateString4 = "Thu, 1 Jan 2015 00:00:00 -0800";
runParseTest(dateString, formatter);
runParseTest(dateString2, formatter);
runParseTest(dateString3, formatter);
runParseTest(dateString4, formatter);
runJava8Test();
}
private static void runParseTest(String dateString, DateFormat formatter) throws ParseException {
System.out.println(" Format: " + FORMAT);
System.out.println(" Formatter time zone: " + formatter.getTimeZone().getDisplayName());
System.out.println(" Parse String: " + dateString);
Date date = formatter.parse(dateString);
System.out.println(" Formatter time zone: " + formatter.getTimeZone().getDisplayName());
System.out.println(" Parsed time in millis: " + date.getTime());
System.out.println(" Parsed date: " + date.toString());
System.out.println();
}
private static void runJava8Test() {
OffsetDateTime parsed = OffsetDateTime
.parse(
"Thu, 1 Jan 2015 00:00:00 -1300",
DateTimeFormatter.ofPattern(FORMAT)
);
System.out.println(" Java 8 parsed offset: " + parsed.getOffset().toString());
}
}
和输出:
Format: EEE, d MMM yyyy HH:mm:ss Z
Formatter time zone: Greenwich Mean Time
Parse String: Thu, 1 Jan 2015 00:00:00 EDT
Formatter time zone: Eastern Standard Time
Parsed time in millis: 1420084800000
Parsed date: Thu Jan 01 04:00:00 GMT 2015
Format: EEE, d MMM yyyy HH:mm:ss Z
Formatter time zone: Eastern Standard Time
Parse String: Thu, 1 Jan 2015 00:00:00 PST
Formatter time zone: Pacific Standard Time
Parsed time in millis: 1420099200000
Parsed date: Thu Jan 01 08:00:00 GMT 2015
Format: EEE, d MMM yyyy HH:mm:ss Z
Formatter time zone: Pacific Standard Time
Parse String: Thu, 1 Jan 2015 00:00:00 +0000
Formatter time zone: Pacific Standard Time
Parsed time in millis: 1420070400000
Parsed date: Thu Jan 01 00:00:00 GMT 2015
Format: EEE, d MMM yyyy HH:mm:ss Z
Formatter time zone: Pacific Standard Time
Parse String: Thu, 1 Jan 2015 00:00:00 -0800
Formatter time zone: Pacific Standard Time
Parsed time in millis: 1420099200000
Parsed date: Thu Jan 01 08:00:00 GMT 2015
Java 8 parsed offset: -13:00