简体   繁体   English

无法使用 AM/PM 标记解析日期时间字符串

[英]Unable to parse DateTime-string with AM/PM marker

The string I want to format looks like this: String datetime = "9/1/10 11:34:35 AM"我要格式化的字符串如下所示: String datetime = "9/1/10 11:34:35 AM"

Following pattern for SimpleDateFormat works: 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]

However I need to parse the AM/PM marker as well, and when I add that to the pattern I receive an exception.但是,我还需要解析 AM/PM 标记,当我将其添加到模式时,我收到一个异常。

Pattern that doesn't work:不起作用的模式:

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

I have tried with this also with same exception:我也试过这个,但有同样的例外:

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

Exception:例外:

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

I have looked through the API at http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html#text but canät seem to find where I do wrong.我浏览了http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html#text 上的 API,但似乎找不到我做错的地方。

Any suggestions?有什么建议吗?

One possibility is that your default Locale has different symbols for AM/PM.一种可能性是您的默认Locale具有不同的 AM/PM 符号。 When constructing a date format you should always supply a Locale unless you really want to use the system's default Locale , eg:在构建日期格式时,您应该始终提供Locale除非您真的想使用系统的默认Locale ,例如:

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

Modern answer:现代答案:

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

This produces a LocalDateTime of 2010-09-01T11:34:35.这会产生 2010-09-01T11:34:35 的LocalDateTime Beware of two digit years, though;不过要注意两位数的年份; DateTimeFormatter will assume 2000 through 2099. For my birthday this would have been incorrect. DateTimeFormatter将假定为 2000 年到 2099 年。对于我的生日,这将是不正确的。

We still need to provide the locale.我们仍然需要提供语言环境。 Since AM/PM markers are hardly used in practice in other locales than English, I considered Locale.ENGLISH a fairly safe bet.由于 AM/PM 标记在英语以外的其他语言环境中几乎不使用,我认为Locale.ENGLISH是一个相当安全的选择。 Please substitute your own.请用自己的代替。

The other answers were fine answers in 2010 and 2011. Already in 2014 the above was valid and I would have preferred it.其他答案在 2010 年和 2011 年都是很好的答案。在 2014 年,上述内容已经有效,我会更喜欢它。

I am taking an example of date given below and print the formatted date into 24-hour format if suits your requirement.我以下面给出的日期为例,如果符合您的要求,将格式化的日期打印为 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();
        }

If you still have any query, Please respond.如果您还有任何疑问,请回复。 Thanks.谢谢。

java.time时间

You can build a case-insensitive parser using DateTimeFormatterBuilder .您可以使用DateTimeFormatterBuilder构建不区分大小写的解析器。 Since a date-time parsing/formatting type (eg DateTimeFormatter , SimpleDateFormat etc.) is Locale -sensitive, you should always use a Locale with such a type.由于日期时间解析/格式化类型(例如DateTimeFormatterSimpleDateFormat等)是Locale敏感的,因此您应该始终使用具有此类类型的Locale I've used Locale.ENGLISH because your date-time string has AM/PM marker in English.我使用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)));;
    }
}

Output:输出:

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

Learn more about the the modern date-time API * from Trail: Date Time .Trail: Date Time 中了解有关现代日期时间 API * 的更多信息。


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project . * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和您的 Android API 工作级别仍然不符合 Java-8,请检查 通过 desugaringHow to use ThreeTenABP in Android Project 可用的 Java 8+ APIs

Just a note about Locale :关于Locale的说明:
the symbols used for AM/PM depend on Locale !用于 AM/PM 的符号取决于Locale

This affects parsing strings, eventually causing errors if the used AM/PM field does not match the predefined symbols.这会影响解析字符串,如果使用的 AM/PM 字段与预定义符号不匹配,最终会导致错误。 (obviously also affects formatting) (显然也会影响格式)

java.time.format.DateTimeFormatter and java.text.SimpleDateFormat accept an optional Locale when being created. java.time.format.DateTimeFormatterjava.text.SimpleDateFormat在创建时接受可选的Locale If none is given.如果没有给出。 the systems default one is used.使用系统默认值。


Warning: using DateTimeFormatter the case of the AM/PM flag is also relevant when parsing, at least for some locales.警告:使用DateTimeFormatter ,AM/PM 标志的情况在解析时也是相关的,至少对于某些语言环境是这样。

As an example, the Indian Locale requires the AM/PM flag being lowercase ( am , pm ), while some other locales ( ROOT , ITALY , US , GERMANY ) only accept uppercase AM/PM.例如,印度语言环境要求 AM/PM 标志为小写( ampm ),而其他一些语言环境( ROOTITALYUSGERMANY )仅接受大写 AM/PM。

This throws DateTimeParseException: Text '2021-03-31 10:15:30 AM +05:30' could not be parsed at index 20这将引发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"))) 

This results in 2021-03-31T10:15:30+05:30这导致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")))

Using Locale.US , Locale.GERMANY or Locale.ROOT , the results are inverted .使用Locale.USLocale.GERMANYLocale.ROOT ,结果是相反的

Note: case of AM/PM does not matter when parsing with SimpleDateFormat (I am not recommending its use, I prefer DateTimeFormatter )注意:使用SimpleDateFormat解析时 AM/PM 的大小写无关紧要(我不推荐使用它,我更喜欢DateTimeFormatter

If you are working with FreeMarker for Java and pop on this issue use below code.如果您正在使用 FreeMarker for Java 并解决此问题,请使用以下代码。 I had this problem, my locale set AM/PM as DE.我遇到了这个问题,我的语言环境将 AM/PM 设置为 DE。 Not sure why... <#setting locale="en_US">不知道为什么... <#setting locale="en_US">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM