0

我正在使用 SimpleDateFormat 将 Date 从 String 类型 Date 转换为 Date 类型 Date,但是我得到的结果日期正在发生变化。谁能告诉我为什么它会发生变化 另外我应该使用什么来从 String而不是获取正确的 Date 类型日期我到这里时换了一个。

    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
4

4 回答 4

2

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

于 2013-01-21T17:06:10.897 回答
2

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

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

java.time

java.util日期时间 API 及其格式化 API已SimpleDateFormat过时且容易出错。建议完全停止使用它们并切换到现代 Date-Time API *

另外,下面引用的是来自Joda-Time主页的通知:

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

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

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

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);
    }
}

输出:

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

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

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

  1. 格式,uuuu-MM-dd HH:mm:ss其中H指定 24 小时格式。对于您的日期时间字符串,您可以使用y而不是,u我更u喜欢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

注意: 切勿在没有 Locale 的情况下使用 SimpleDateFormat 或 DateTimeFormatter

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


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

于 2021-07-03T15:59:39.070 回答
1

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

于 2013-01-21T17:05:13.663 回答
1

您正在使用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实际上有时区信息,而实际上没有时区信息。
于 2013-01-21T17:07:30.607 回答