【问题标题】:Java : SimpleDateFormat - Unable to parse a string to a date of desired formatJava:SimpleDateFormat - 无法将字符串解析为所需格式的日期
【发布时间】:2012-03-05 08:42:39
【问题描述】:

我正在尝试将一个字符串解析为yyyy-MM-dd 格式,并将一个字符串解析为yyyy-MM-dd HH:mm:ss。 我正在使用SimpleDateFormat

我之前成功地使用了相同的方法,但现在出了点问题。我得到标准格式的日期,即Tue Mar 05 00:00:00 GMT+05:30 2012(对于yyyy-MM-dd)和Mon Mar 05 13:01:35 GMT+05:30 2012(对于yyyy-MM-dd HH:mm:ss),因为我需要它们分别是2012-03-052012-03-05 13:01:35

这就是我的工作:

Date today = new Date();
SimpleDateFormat tsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
    today = tsdf.parse(tsdf.format(new Date()));
} catch(Exception e) {
    System.out.println("Error occurred"+ e.getMessage());
}

System.out.println(today);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
    // I recieve a string in this format here (refers to 5 march 2012).
    myDate = sdf.parse('2012-03-05');            
    System.out.println(myDate);
} catch(Exception e) {
    System.out.println("Error occurred "+ e.getMessage());
}

【问题讨论】:

  • 您遇到了什么错误?有堆栈跟踪吗?或者你得到日期的格式是什么?
  • '2012-03-05' 应该是 "2012-03-05"
  • 请显示异常堆栈跟踪(由 e.printStackTrace() 生成)
  • 第二个例子是编译时错误——应该是sdf.parse("2012-03-05")
  • @TrueDub:没有错误。只不过是格式错误的日期。

标签: java simpledateformat java.util.date


【解决方案1】:

您不是在输出作为格式化程序结果的字符串,而是在输出实际的日期对象。这将始终是 Date.toString() 的结果,对于您使用的 JDK,它就是您看到的格式。不要将格式化后的字符串转回日期对象,直接打印出来!

SimpleDateFormat tsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
    String formattedDate = tsdf.format(new Date());
} catch(Exception e) {
    System.out.println("Error occurred"+ e.getMessage());
}

System.out.println(formattedDate);

您不能将“格式”应用于java.util.Date 对象以供以后使用。它只是一个原始的毫秒数,它的 toString 方法将始终打印相同的表示。您必须将其转换为格式化字符串并使用该字符串。

【讨论】:

  • 是否需要try-catch tsdf.format(new Date())?我知道 tsdf.parse(String date) 需要 try-catch,但我不相信 tsdf.format(Date date) 需要它。
【解决方案2】:
today = tsdf.parse(tsdf.format(new Date()));
System.out.println(today);

在我看来,正如您所期望的那样,Date 实例被格式化。事实并非如此。 Date 实例表示可以格式化“到”字符串的日期。它是一个简单地保存 long 值的类(意思是“以毫秒为单位的时间”)。

这将给出预期的结果:

Date today = new Date();
String formattedDate = tsdf.format(today);
System.println(formattedDate);     // <- we print the string!!

【讨论】:

  • 你说得对,我以为日期对象被格式化了。其实我不需要打印日期,我想在数据库中插入一条包含这个日期的记录。插入时出错。
  • 什么样的错误?注意使用正确的类:您可能需要java.sql.Date 而不是java.util.Date
【解决方案3】:

如果要格式化Date 实例,则不必使用parse 方法,必须使用format 方法,如下所示:

    Date today = new Date();
    SimpleDateFormat tsdf = new SimpleDateFormat("yyyy-MM-dd");
    try
    {
        System.out.println(tsdf.format(today));
    }
    catch (Exception e)
    {
        System.out.println("Error occurred" + e.getMessage());
    }

parse 方法用于将字符串转换为日期,format 方法用于将Date 实例格式化为指定格式的字符串。

【讨论】:

    【解决方案4】:

    java.time

    您正在使用旧的麻烦的日期时间类,现在已被 java.time 类取代。

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如java.util.Date.Calendarjava.text.SimpleDateFormatJoda-Time 团队还建议迁移到 java.time。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

    大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。

    LocalDate

    对于仅日期值,请使用 LocalDate 类。您的输入值采用标准 ISO 8601 格式。默认情况下,java.time 类中使用 ISO 8601 格式来解析和生成表示日期时间值的字符串。所以不需要指定格式模式。

    LocalDate localDate = LocalDate.parse( "2012-03-05" );
    

    要生成这样的字符串,请调用toString

    String output = localDate.toString();
    

    LocalDateTime

    对于像2012-03-05 12:34:56 这样的字符串,我们遇到了问题。未指示与 UTC 或时区的偏移量。所以它并不代表时间线上的一个实际时刻,而是一个关于可能时刻的粗略概念。这个非时刻在 java.time 中由 LocalDateTime 类表示。

    您的字符串格式是 ISO 8601 的变体,而规范版本的中间是 T 而不是空格。因此,一种选择是将 SPACE 替换为 T

    LocalDateTime ldt = LocalDateTime.parse( "2012-03-05 12:34:56".replace( " " , "T" );
    

    或者定义一个模式。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd hh:mm:ss" );
    LocalDateTime ldt = LocalDateTime.parse( "2012-03-05 12:34:56" , formatter );
    

    避免使用此类缺少偏移量或时区信息的日期时间格式,如果它们确实旨在表示时间轴上的实际时刻。

    ZonedDateTime

    要赋予该值含义,要确定时间线上的实际时刻,我们需要指定日期时间所针对的时区。

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = ldt.atZone( zoneId );
    

    调用toString 会生成一个格式为扩展ISO 8601 标准格式的字符串,方法是在方括号中附加时区名称。

    String output = zdt.toString(); // Yields: 2012-03-05T12:34:56-04:00[America/Montreal]
    

    如果您想省略T,您可以使用String::replace 方法替换为空格。或者使用格式化程序。如果您真的想要问题中缺少任何偏移量或时区信息的字符串(违反我的建议),请使用上面显示的相同格式化程序。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd hh:mm:ss" );  // Not recommended as it lacks offset/zone info.
    String output = zdt.format( formatter );  // Yields: 2012-03-05 12:34:56
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 2019-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多