【问题标题】:Java - Date format for Multiple ScenariosJava - 多场景的日期格式
【发布时间】:2019-05-08 16:33:44
【问题描述】:

我有一个 java 组件来格式化我检索的日期。这是我的代码:

    Format formatter      = new SimpleDateFormat("yyyyMMdd");
        String s = "2019-04-23 06:57:00.0";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss.S");
        try
        {
            Date date = simpleDateFormat.parse(s);
            System.out.println("Formatter: "+formatter.format(date));
        }
        catch (ParseException ex)
        {
            System.out.println("Exception "+ex);
        }   

只要 String s 的格式为 "2019-04-23 06:57:00.0";,代码就可以很好地工作

我的问题是,如何调整此代码,使其适用于以下场景,例如, 我的s 字符串可能具有像

这样的值

String s = "2019-04-23 06:57:00.0";
or 
String s = "2019-04-23 06:57:00";

Or 
String s = "2019-04-23";

如果我没有通过毫秒,现在它会失败。谢谢!

【问题讨论】:

标签: java datetime formatting


【解决方案1】:

不同的类型

String s = "2019-04-23 06:57:00";

String s = "2019-04-23";

这是两种不同的信息。一个是带有时间的日期,另一个只是一个日期。因此,您应该将每个对象解析为不同类型的对象。

LocalDateTime.parse

要符合LocalDateTime 类中默认使用的ISO 8601 标准格式,请将中间的空格替换为T。我建议您教育数据的发布者在将日期时间值作为文本交换时仅使用 ISO 8601 格式。

LocalDateTime ldt1 = LocalDateTime.parse( "2019-04-23 06:57:00".replace( " " , "T" ) ) ;

默认情况下也会解析小数秒。

LocalDateTime ldt2 = LocalDateTime.parse( "2019-04-23 06:57:00.0".replace( " " , "T" ) ) ;

看到这个code run live at IdeOne.com

ldt1.toString(): 2019-04-23T06:57

ldt2.toString(): 2019-04-23T06:57

LocalDate.parse

您的仅日期输入已经符合ISO 8601

LocalDate ld = LocalDate.parse( "2019-04-23" ) ;

看到这个code run live at IdeOne.com

ld.toString(): 2019-04-23

日期与时间

您可以从日期中去掉时间。

LocalDate ld = ldt.toLocalDate() ;

你可以重新添加它。

LocalTime lt = LocalTime.parse( "06:57:00" ) ;
LocalDateTime ldt = ld.with( lt ) ;

时刻

但是,请注意LocalDateTime 确实代表一个时刻,不是时间轴上的一个点。缺少 time zoneoffset-from-UTC 的上下文,LocalDateTime 无法保持片刻,如其类 JavaDoc 中所述。

暂时使用ZonedDateTimeOffsetDateTimeInstant 类。指导数据的发布者包含偏移量,最好是 UTC。

避免使用旧的日期时间类

旧的类SimpleDateFormatDateCalendar 很糟糕,充斥着糟糕的设计选择,由不熟悉日期时间处理的人编写。这些在几年前被 JSR 310 中定义的现代 java.time 类所取代。

【讨论】:

  • 谢谢.. 这些值来自数据库,所以我认为它符合标准。我会验证这方面的。
  • @Anto 如果您从数据库接收数据,您应该提取日期时间对象,而不仅仅是字符串。将 ResultSet::getObject 与 JDBC 4.2 或更高版本的驱动程序一起使用,以从 DATE 列中获取 LocalDate 对象,并从 TIMESTAMP WITHOUT TIME ZONE 列中获取 LocalDateTime 对象。这已经在 Stack Overflow 上讨论过很多次了。您应该在问题中将数据库作为来源。
【解决方案2】:

如果您在模式中有可选部分,您可以使用[]

例如

public static Instant toInstant(final String timeStr){
    final DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("yyyy-MM-dd HH[:mm[:ss[ SSSSSSSS]]]")
            .withZone(ZoneId.of("UTC"));
    try {
        return Instant.from(formatter.parse(timeStr));
    }catch (DateTimeException e){
        final DateTimeFormatter formatter2 = DateTimeFormatter
                .ofPattern("yyyy-MM-dd")
                .withZone(ZoneId.of("UTC"));
        return LocalDate.parse(timeStr, formatter2).atStartOfDay().atZone(ZoneId.of("UTC")).toInstant();
    }
}

封面

  • yyyy-MM-dd
  • yyyy-MM-dd HH
  • yyyy-MM-dd HH:mm
  • yyyy-MM-dd HH:mm:ss
  • yyyy-MM-dd HH:mm:ss SSSSSSSS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2010-09-29
    • 2011-11-16
    • 1970-01-01
    相关资源
    最近更新 更多