【问题标题】:How to get correct date after conversion from String to date从字符串转换为日期后如何获得正确的日期
【发布时间】:2013-01-21 17:02:10
【问题描述】:

我正在将日期从字符串类型日期转换为日期类型日期,使用 SimpleDateFormat 但 结果我得到的日期正在改变。谁能告诉我为什么它会改变 另外我应该使用什么来从字符串中获取正确的日期类型日期,而不是在我到达这里时更改的日期。

    Date d = null;
    String startTime="2012-03-17 16:00:00 PM";
    DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
    try {
          d=  sdf.parse(startTime);
         } catch (ParseException e) {}

System.out.println("DD="+d) //printing Sun Mar 18 04:00:00 IST 2012 ? why this 
   //Date enterd was 17 Mar 2012

【问题讨论】:

  • 我很惊讶它完全有效,因为您使用的 hh(范围 1-12)的值为 16。
  • 您指定了 AM/PM 周期。这是基于 12 小时,而不是 24 小时。
  • @Jon Skeet:这并不奇怪。 DateFormat 默认使用“宽松”日历操作,因此溢出字段将导致下一个更重要的字段在尝试使设置的字段在有效范围内时递增。

标签: java date simpledateformat


【解决方案1】:

如果您将 24 小时制时钟和 AM/PM 标记结合使用,则会产生歧义。在您的情况下,您应该使用“HH”(大写 H)来解析 0-23 范围内的小时字段并忽略 AM/PM 后缀,或者使用带有适当 AM/PM 后缀的 12 小时制(在您的情况下为“04 :00:00 PM")。

【讨论】:

    【解决方案2】:

    您输入的日期时间字符串错误。

    AM/PM 标记不适用于 24 小时格式的时间。它应该是2012-03-17 04:00:00 PM2012-03-17 16:00:00

    java.time

    java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

    另外,下面引用的是来自home page of Joda-Time的通知:

    请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。

    使用现代日期时间 API java.time 的解决方案:

    让我们首先尝试按照您的方式进行操作:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String startDateTime = "2012-03-17 16:00:00 PM";
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd hh:mm:ss a", Locale.ENGLISH);
            LocalDateTime ldt = LocalDateTime.parse(startDateTime, dtf);
            System.out.println(ldt);
        }
    }
    

    输出:

    线程“主”java.time.format.DateTimeParseException 中的异常: 无法解析文本“2012-03-17 16:00:00 PM”:值无效 ClockHourOfAmPm(有效值 1 - 12):16

    如您所见,java.time API 正确地引发了异常,通知您该问题。另一方面,SimpleDateFormat 错误地解析了输入字符串。

    现在,让我们看看如何正确解析它。为了正确解析它,我们将使用:

    1. 格式 uuuu-MM-dd HH:mm:ss 其中H 指定 24 小时格式。对于您的日期时间字符串,您可以使用 y 而不是 uI prefer u to y
    2. 函数DateTimeFormatter#parse(CharSequence, ParsePosition)ParsePosition 索引设置为0

    演示:

    import java.text.ParsePosition;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String startDateTime = "2012-03-17 16:00:00 PM";
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
            ParsePosition pp = new ParsePosition(0);
            LocalDateTime ldt = LocalDateTime.from(dtf.parse(startDateTime, pp));
            System.out.println(ldt);
        }
    }
    

    输出:

    2012-03-17T16:00
    

    ONLINE DEMO

    注意:Never use SimpleDateFormat or DateTimeFormatter without a Locale.

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。


    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      【解决方案3】:

      16:00:00 PM 不是有效时间,SimpleDateFormat 会将其转换为第二天凌晨 4:00。

      【讨论】:

      • 他也必须使用“HH”而不是“hh”来表示 24 小时制。
      • +1,或“2012-03-17 4:00:00 PM”的开始时间,原格式
      【解决方案4】:

      您在格式字符串中使用了hh,这是一种 12 小时格式。这是有道理的,因为您也有一个 AM/PM 指示符 (a)...但是对于 16 的值,它没有意义

      我怀疑“下午 16 点”转换为第二天凌晨 4 点,因此出现了问题。 (奇怪的是,使用setLenient(false) 不会发现这个错误。)

      要么使用"yyyy-MM-dd HH:mm:ss"的格式并确保最后没有“PM”,使用现有格式但给它合理的值(04 而不是 16)。

      另外,我建议:

      • 在 Java 中使用 Joda Time 通常是处理日期/时间的好主意
      • 不要像这样吞下ParseException。空的 catch 块是一个非常糟糕的主意。
      • 当您调用始终使用默认时区的Date.toString() 时,您无法更改输出格式。有时这没关系,用于快速诊断,但它可能给人一种误导的印象,即Date 实际上有时区信息,而实际上它没有。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-27
        • 2021-07-14
        • 2020-05-10
        • 2011-11-28
        • 2016-11-10
        相关资源
        最近更新 更多