2017-06-17 146 views
1

我已实现了以下方法将String转换为Date,因为Date(String)构造被弃用:转换字符串到日期 - Java的

private Date format(String inputString) { 
     DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); 
     try { 
      return dateFormat.parse(inputString); 
     } catch (ParseException e) { 
      return new Date(); 
     } 
    } 

一个inputString样品2017-06-01T01:00:00Z。但是,当我检查输出时,我观察到异常处理程序被触发并返回new Date(),这意味着我的模式有问题:"Jun 17, 2017 1:12:02 PM"

我缺少什么模式yyyy-MM-dd'T'HH:mm:ssZ

+4

我不能更强烈地建议不要使用传统的'java.util.Date'类。您应该改用'java.time'包中的相应类。 –

+1

您可以打印正在捕获的异常的堆栈跟踪,然后在此处发布输出? – csmckelvey

+2

您应该考虑不推荐使用java.util.Date。整个东西。 –

回答

1

你在输入字符串中有一个字面的Z,所以你也需要引用它(或使用X)。像,

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

更好(如在评论中指出)

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); 

另外,不要扔掉异常(至少打印堆栈跟踪)。在Java 8+中,您应该使用新的java.time类。这可能看起来像,

private static LocalDateTime format(String inputString) { 
    String pattern = "yyyy-MM-dd'T'HH:mm:ssX"; 
    return LocalDateTime.from(DateTimeFormatter.ofPattern(pattern) 
      .parse(inputString)); 
} 
+2

我敢打赌,输入字符串中的'Z'是时区,而不仅仅是一个文字。因此,使用'X'(ISO8601时区)而不是''Z''会更合适...... –

+2

本答案给出**差的建议**。通过将'Z'视为文字并忽略它,您忽略了至关重要的信息:时区或与UTC的偏移量。您丢弃的信息没有获得任何好处。同样,'LocalDateTime'类故意缺少关于偏移量或区域的信息 - 当缺少这样的信息时适当,但是有意使用丢弃信息是愚蠢的。 'LocalDateTime'确实代表时间轴上的一个时刻。查看Ole V.V.的[更好的建议来使用java.time类并保留区域/偏移量信息](https://stackoverflow.com/a/44609474/642706)。 –

+1

感谢您的编辑。这是对老式代码的改进。在现代代码中,您仍然有效地丢弃时区信息。只有在您知道丢失的区域信息是“Z”之前,现在您不再检查并且无法确定。这更糟糕...... –

4

Z模式表示数值时区偏移量。因此这里要求的抵消将是+0000

X模式将允许您使用时区偏移量,如Z。 (是的,这似乎是违反直觉的,但你去那里。)

Source

3

我同意乔C和路易斯瓦塞尔曼点评:留了早已过时的Date类,如果有什么办法可以。还有。现代化的替代课程非常方便和程序员友好。

此外,您的输入字符串符合ISO 8601标准的瞬间即时点,因此适合Instant类。不需要任何明确的格式化器来解析它。我建议:

private static Instant parse(String inputString) { 
    try { 
     return Instant.parse(inputString); 
    } catch (DateTimeParseException dtpe) { 
     System.err.println("Parsing: " + dtpe); 
     return Instant.now(); 
    } 
} 

使用如下的方法,例如:

String inputString = "2017-06-01T01:00:00Z"; 
    System.out.println(parse(inputString)); 

此打印:

2017-06-01T01:00:00Z 

嗯,这是你从开始时相同的字符串,因为Instant.toString()产生相同的ISO 8601字符串。

我也承认scottb:我们有时需要与传统代码进行互操作,而这些代码确实需要一个陈旧的实例Date实例。如果这是你的情况,从Date.from(parse(inputString))产生一个。这将产生一个Date等于瞬间(在我的电脑上打印为Thu Jun 01 03:00:00 CEST 2017,因为那恰好是我的时区)。在任何情况下,我建议在输入您的遗留代码之前在最后一刻转换为Date以最大限度地减少您对它的使用。

只是为了实验,让我们尝试用你的格式不正确的模式字符串与新DateTimeFormatter类:

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ").parse(inputString); 

这将产生java.time.format.DateTimeParseException: Text '2017-06-01T01:00:00Z' could not be parsed at index 19。它试图对你有所帮助:2017-06-01T01:00:00Z的索引19是Z。正如另外两个答案所说,这正是格式模式与输入不匹配的地方。相信我的话,这只是一个例子,你可以从现代课程中获得更好的帮助,而不是从旧课程中获得更多帮助。