如何使用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仍然是正确的。

时区的日期? LocalDateDate都不能在其中包含时区,因此您需要单独获取偏移信息。 有趣的是,您的字符串似乎遵循“ISO-8601-like”格式的偏移日期,甚至由名称中包含ISO的内置格式化程序表示。 如果Java包含OffsetDateZonedDate类,我希望这样的类将您的字符串解析为一个对象,甚至没有明确的格式化程序。 不幸的是,据我所知,即使在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的数据类型中定义的词法值空间。