如何使用TimeZone将String转换为Date?

时间:2018-01-24 09:31:07

标签: java date datetime time timezone

我正在尝试转换String +时区中的Date。 我从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”)

3 个答案:

答案 0 :(得分:1)

输入有一个日期 - 年,月,日 - 和偏移量 - difference from 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 与时区相同。查看差异here

答案 1 :(得分:0)

    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日期和时间API java.time,建议您也这样做。 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项目中也没有这样的课程。

<强>链接

答案 2 :(得分:0)

  

&#34; 2017年1月3日+ 01:00&#34;

我认为它类似于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的表示:日期。

   返回:由...表示的Calendar值   字符串参数。

   抛出:IllegalArgumentException - 如果是string   参数不符合XML中定义的词汇值空间   架构第2部分:xsd的数据类型:日期。