如何从String转换为日期后获得正确的日期

时间:2013-01-21 17:02:10

标签: java date simpledateformat

我将Date从String类型Date转换为Date类型Date,使用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

4 个答案:

答案 0 :(得分:2)

如果您将24小时时钟和AM / PM标记结合使用,那就很不方便了。在您的情况下,您应该使用“HH”(大写字母H)来解析0-23范围内的小时字段并忽略AM / PM后缀或使用具有适当AM / PM后缀的12小时时钟(在您的情况下为“04”) :00:00 PM“)。

答案 1 :(得分: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 的核心部分,取代了该项目。

使用 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.time API 会正确抛出异常,通知您有关问题。另一方面,SimpleDateFormat 会错误地解析输入字符串。

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

  1. 格式,uuuu-MM-dd HH:mm:ss,其中 H 指定 24 小时格式。对于日期时间字符串,您可以使用 y 而不是 u 而是 I 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 了解有关现代 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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

我怀疑“下午16点”正在翻译到第二天凌晨4点,因此出现问题。 (奇怪的是,使用setLenient(false) 不会选择此错误。)

要么使用"yyyy-MM-dd HH:mm:ss"格式并确保最后没有“PM”,使用现有格式但是给它明智的价值观(04代替16)。

另外,我建议:

  • 使用Joda Time通常是Java中日期/时间工作的好主意
  • 不要像这样吞下ParseException。空抓块是一个非常糟糕的主意。
  • 当您致电始终使用默认时区的Date.toString()时,您无法更改输出格式。对于快速诊断而言,有时候也没关系,但它会给人一种误导性的印象,即Date实际上有时区信息,而不是。{/ li>