如何使用TimeZone将String转换为Date?
我正在尝试在Date
+ Timezone中转换我的String
。 我从DateTime
变量获取我的String(这里是:xyz)。 我的代码:
String abc = xyz.toString("yyyy-MM-ddZZ"); java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-ddXXX"); java.util.Date date = sdf.parse(abc); System.out.println("Date: " + sdf.format(date));
错误:
格式无效:“2017-01-03 + 01:00”格式错误为“+01:00”
如果我尝试SimpleDateFormat("yyyy-MM-dd");
它工作但没有时区(“+01:00”)
输入有一个日期 – 年,月,日 – 和偏移 – 与UTC的差异 – 但要构建java.util.Date
,您还需要时间:小时,分钟,秒,分数秒。
SimpleDateFormat
非常糟糕,因为它会做一些“魔术”,将缺少的字段设置为默认值。 另一个问题是X
模式不适用于所有Java版本,文档也很糟糕。
您可以使用新的Java 8类,如上所述。 使用它们,您可以解析输入,选择要用于时间字段的默认值并转换为java.util.Date
,如果这是您需要的:
DateTimeFormatter fmt = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_OFFSET_DATE) // set hour to midnight .parseDefaulting(ChronoField.HOUR_OF_DAY, 0).toFormatter(); OffsetDateTime odt = OffsetDateTime.parse("2017-01-03+01:00", fmt); // 2017-01-03T00:00+01:00
OffsetDateTime
将时间设置为午夜,但您可以将其更改为您需要的任何值,而使用SimpleDateFormat
则不可能,因为它使用内部默认值而您无法控制它。
并且日期和偏移量已正确设置为输入字符串中的值。 如果需要,您可以转换为java.util.Date
:
Date date = Date.from(odt.toInstant());
如果您愿意,您还可以获得日期的各个“部分”:
// get just the date LocalDate localDate = odt.toLocalDate(); // 2017-01-03 // get just the offset ZoneOffset offset = odt.getOffset(); // +01:00
PS:偏移量+01:00
与时区不同。 看到这里的差异
String abc = "2017-01-03+01:00"; TemporalAccessor parsed = DateTimeFormatter.ISO_OFFSET_DATE.parse(abc); LocalDate date = LocalDate.from(parsed); ZoneOffset offset = ZoneOffset.from(parsed); System.out.println("Date: " + date + "; offset: " + offset + '.');
这打印:
Date: 2017-01-03; offset: +01:00.
我正在使用java.time
,现代Java日期和时间API,并建议你这样做。 Date
类已经过时了(抱歉,没有双关语)和SimpleDateFormat
尤其出了名的麻烦。 不要使用它们。 现代API可以更好地使用。 只有当您需要一个无法更改的旧API的java.util.Date
和/或java.util.TimeZone
,才能像这样转换:
Date oldfashionedDate = Date.from(date.atStartOfDay(offset).toInstant()); TimeZone oldfashionedTimeZone = TimeZone.getTimeZone(offset); System.out.println("Old-fashioned date: " + oldfashionedDate + "; old-fashioned time-zone: " + oldfashionedTimeZone.getDisplayName() + '.');
在我的电脑上打印:
Old-fashioned date: Tue Jan 03 00:00:00 CET 2017; old-fashioned time-zone: GMT+01:00.
我恰好处于一个与你偏离UTC一致的时区,所以很明显转换得到了正确的结果。 在其他时区,输出将更加混乱,因为Date.toString()
使用JVM的时区设置来生成字符串,但Date
仍然是正确的。
带时区的日期? LocalDate
和Date
都不能在其中包含时区,因此您需要单独获取偏移信息。 有趣的是,您的字符串似乎遵循“ISO-8601-like”格式的偏移日期,甚至由名称中包含ISO的内置格式化程序表示。 如果Java包含OffsetDate
或ZonedDate
类,我希望这样的类将您的字符串解析为一个对象,甚至没有明确的格式化程序。 不幸的是,据我所知,即使在ThreeTen-Extra项目中也没有这样的课程。
链接
- Oracle教程:Date Time ,解释了如何使用
java.time
。 - ThreeTen Extra ,与
java.time
一起开发的更多类。 - 编辑: 查看我在ideone上运行的更新代码 。
“2017年1月3日+ 01:00”
我认为它类似于ISO 8601格式的日期字符串,但实际上不是ISO 8601 。 谢谢@Meno Hochschild和@Basil Bourque的指示。
很幸运,这个方法适用于这种格式的字符串: javax.xml.bind.DatatypeConverter.parseDateTime
,它将返回一个Calendar
:
System.out.println(DatatypeConverter.parseDate("2017-01-03+01:00").getTime());
输出:
Tue Jan 03 07:00:00 CST 2017
从方法javadoc:
public static Calendar parseDate(String lexicalXSDDate)
将字符串参数转换为Calendar值。参数:lexicalXSDDate – 包含xsd:Date的词汇表示的字符串。
返回:由字符串参数表示的Calendar值。
抛出:IllegalArgumentException – 如果string参数不符合XML Schema Part 2:xsd:Date的数据类型中定义的词法值空间。