无法使用AM / PM标记解析DateTime-string

时间:2010-09-01 13:41:22

标签: java simpledateformat

我要格式化的字符串如下所示: String datetime =“9/1/10 11:34:35 AM”

以下SimpleDateFormat模式有效:

SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss");
Date d = sdf.parse(datetime);
System.out.println(d);

Output> [Wed Sep 01 11:34:35 CEST 2010]

但是我也需要解析AM / PM标记,当我将其添加到模式时,我会收到异常。

不起作用的模式:

SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss a");

我也尝试了同样的例外:

SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss aa");

例外:

java.text.ParseException: Unparseable date: "9/1/10 11:34:35 AM"

我在http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html#text查看了API,但似乎无法找到我做错的地方。

有什么建议吗?

6 个答案:

答案 0 :(得分:31)

一种可能性是您的默认Locale具有不同的AM / PM符号。构建日期格式时,除非您确实要使用系统的默认Locale,否则应始终提供Locale,例如:

SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm:ss a", Locale.US)

答案 1 :(得分:3)

我正在举例说明下面给出的日期,如果符合您的要求,请将格式化的日期打印成24小时格式。

 String inputdate="9/1/10 11:34:35 AM";
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd/MM/yy hh:mm:ss aa",Locale.getDefault());
        try {
            System.out.println(""+new SimpleDateFormat("dd/MM/yy HH:mm:ss",Locale.getDefault()).format(simpleDateFormat.parse(inputdate)));

        } catch (ParseException e) {
            e.printStackTrace();
        }

如果您还有任何疑问,请回复。感谢。

答案 2 :(得分:1)

现代回答:

    String datetime = "9/1/10 11:34:35 AM";
    LocalDateTime dt = LocalDateTime.parse(datetime, 
            DateTimeFormatter.ofPattern("M/d/yy h:mm:ss a", Locale.ENGLISH));

这将产生2010-09-01T11:34:35的LocalDateTime。但要注意两位数的年份; DateTimeFormatter将假设2000年到2099年。对于我的生日,这将是不正确的。

我们仍然需要提供语言环境。由于在英语以外的其他语言环境中,AM / PM标记很难用于实践,我认为Locale.ENGLISH是一个相当安全的选择。请替换你自己的。

其他答案在2010年和2011年都是很好的答案。在2014年,上述内容已经有效,我更喜欢它。

答案 3 :(得分:1)

java.time

您可以使用 DateTimeFormatterBuilder 构建不区分大小写的解析器。由于日期时间解析/格式化类型(例如 DateTimeFormatterSimpleDateFormat 等)对 Locale 敏感,因此您应该始终使用具有此类类型的 Locale。我使用 Locale.ENGLISH 是因为您的日期时间字符串有英文 AM/PM 标记。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .parseCaseInsensitive()
                                .appendPattern("M/d/uu H:m:s a")
                                .toFormatter(Locale.ENGLISH);
        
        //Test
        Stream.of(
                "9/1/10 11:34:35 AM",
                "9/1/10 11:34:35 am",
                "09/1/10 11:34:35 AM",
                "9/01/10 11:34:35 Am"
        ).forEach(s -> System.out.println(LocalDateTime.parse(s, dtf)));;
    }
}

输出:

2010-09-01T11:34:35
2010-09-01T11:34:35
2010-09-01T11:34:35
2010-09-01T11:34:35

modern date-time API 中了解有关 Trail: Date Time* 的更多信息。


* 出于任何原因,如果您必须坚持使用 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

答案 4 :(得分:0)

如果您正在使用FreeMarker for Java并在此问题上弹出,请使用以下代码。我有这个问题,我的语言环境将AM / PM设置为DE。不知道为什么...... <#setting locale="en_US">

答案 5 :(得分:0)

关于Locale的注意事项:
用于 AM/PM 的符号取决于 Locale

这会影响解析字符串,如果使用的 AM/PM 字段与预定义的符号不匹配,最终会导致错误。 (显然也会影响格式)

java.time.format.DateTimeFormatterjava.text.SimpleDateFormat 在创建时接受可选的 Locale。如果没有给出。使用系统默认的。


警告:使用 DateTimeFormatter AM/PM 标志的情况在解析时也是相关的,至少对于某些语言环境是这样。

例如,印度语言环境要求 AM/PM 标志为小写(ampm),而其他一些语言环境(ROOTITALY、{ {1}}、US) 只接受大写的 AM/PM。

这会抛出 GERMANY

DateTimeParseException: Text '2021-03-31 10:15:30 AM +05:30' could not be parsed at index 20

这导致 ZonedDateTime.parse("2021-03-31 10:15:30 AM +05:30", DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a Z", new Locale("en", "IN")))

2021-03-31T10:15:30+05:30

使用 ZonedDateTime.parse("2021-03-31 10:15:30 am +05:30", DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a Z", new Locale("en", "IN"))) Locale.USLocale.GERMANY,结果反转

注意:使用 Locale.ROOT 解析时 AM/PM 的大小写无关紧要(我不推荐使用它,我更喜欢 SimpleDateFormat