如何使用时区将字符串转换为日期?



我正在尝试以Date+时区转换我的String。 我从DateTime变量(这里: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"格式,该格式甚至由名称中包含 ISO 的内置格式化程序表示。如果 Java 包含一个OffsetDate或一个ZonedDate类,我希望这样的类将你的字符串解析为一个对象,即使没有显式格式化程序。不幸的是,据我一目了然,不存在这样的类,即使在 ThreeTen-Extra 项目中也是如此。

链接

  • Oracle 教程:日期时间,说明如何使用java.time
  • ThreeTen Extra,随着java.time开发的更多类。
  • 编辑:看到我更新的代码在ideone上实时运行。

"2017-01-03+01:00">

我认为它是类似的ISO 8601格式日期字符串,但实际上不是ISO 8601。感谢@Meno霍克希尔德和@Basil布尔克的指示。

幸运的是,此方法适用于这种格式的字符串:javax.xml.bind.DatatypeConverter.parseDateTime,它将返回一个Calendar

System.out.println(DatatypeConverter.parseDate("2017-01-03+01:00").getTime());

输出:

星期二 1月 03 07:00:00 CST 2017

从方法javadoc:

公共静态日历分析日期(字符串词法 XSDDate)将
字符串参数转换为日历值。

参数:词法XSDDate - 包含词法的字符串 xsd:日期的表示形式。

返回:日历值,表示如下 字符串参数。

抛出:非法参数异常 - if 字符串 参数不符合 XML 中定义的词法值空间 架构第 2 部分:xsd:Date 的数据类型。

相关内容

  • 没有找到相关文章

最新更新