无法将单个数字小时和小写的am-pm解析为Java 8 LocalTime

时间:2017-09-29 01:34:58

标签: datetime java-8 java-time localtime datetime-parsing

当我尝试运行以下代码时:

outputFile.open((std::string(argv[1]) + "_output.txt").c_str(), ofstream::out);

我明白了:

LocalTime test = LocalTime.parse("8:00am", DateTimeFormatter.ofPattern("hh:mma"));

知道为什么会这样吗?

6 个答案:

答案 0 :(得分:5)

AM / PM令牌*为大写:

class Test {
public:
    struct Data {
        const char* first;
        int number;
        int count;

        ~Data() {
            delete[] first;
        }
    };

    Test(const char *alp) {
        // Default constructor initialises struct's fields to 0.
        myStruct = Data();
        myStruct.count = 7;
    }

private:
    Data myStruct;
};

小时的模式定义:

LocalTime test = LocalTime.parse("8:00AM", DateTimeFormatter.ofPattern("hh:mma"));

有关所有可用模式,请参阅Symbol Meaning Presentation Examples ------ ------------ ------------ -------- a am-pm-of-day text PM h clock-hour-of-am-pm (1-12) number 12 K hour-of-am-pm (0-11) number 0 k clock-hour-of-am-pm (1-24) number 0 H hour-of-day (0-23) number 0 javadoc:https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

- 编辑

*根据@ Hugo的评论,这与您设置格式化程序的Locale有关。如果未指定任何内容,则使用JVM默认值。只是发生了绝大多数Locales强制AM / PM令牌为大写:

  

对于大多数语言环境来说,使用大写的AM会发生这种情况,因此它适用于大多数人。但它也可以是ga_IE和es_US语言环境中的a.m.,日语中的午前(ja_JP),瑞典语中的fm(sv_SE)以及许多其他语言。我已经在JDK 1.8.0_144中进行了测试,它有160个语言环境 - 其中108个使用AM - 无论如何,如果您的JVM使用其中一个108个语言环境(并且没有人更改此配置),那么这不是问题< / p>

答案 1 :(得分:3)

AM/PM模式对区域设置敏感。如果您创建格式化程序但未设置java.util.Locale,则它将使用JVM的默认值。无论如何,我已经检查过JDK 1.8.0_144并且没有使用小写am作为AM/PM字段文本的语言环境(我发现使用a.m.和{{1的语言环境},但没有AM)。

因此,另一种方法是设置使用am的区域设置(例如:AM)并使用Locale.ENGLISH构建不区分大小写的格式化程序。另一个细节是输入中的小时只有1位数,因此您必须将模式更改为java.time.format.DateTimeFormatterBuilder(接受1或2位数,而h仅接受2位数):

hh

问题是语言环境也会影响其他字段(例如,如果您使用月份或星期几的名称,或者week based fields)。

另一个细节是格式化程序仅对解析不区分大小写。格式化时,它将使用特定于语言环境的符号,在本例中为大写。所以这个:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // case insensitive
    .parseCaseInsensitive()
    // pattern
    .appendPattern("h:mma")
    // set Locale that uses "AM" and "PM"
    .toFormatter(Locale.ENGLISH);
// now it works
LocalTime test = LocalTime.parse("8:00am", fmt);

打印:

  

8:00 AM

要不依赖于区域设置,您可以使用System.out.println(fmt.format(test)); // 8:00AM

为此字段使用自定义文本地图
java.time.temporal.ChronoField

与前一格式化程序的不同之处在于它使用自定义文本(小写// map of custom text for AM/PM field Map<Long, String> map = new HashMap<>(); // AM's value is 0 map.put(0L, "am"); // PM's value is 1 map.put(1L, "pm"); DateTimeFormatter fmt = new DateTimeFormatterBuilder() // pattern (hour:minute) .appendPattern("h:mm") // use custom text for AM/PM .appendText(ChronoField.AMPM_OF_DAY, map) // create formatter, no need to set locale .toFormatter(); // it also works LocalTime test = LocalTime.parse("8:00am", fmt); am)进行解析和格式化。所以这段代码:

pm

将打印:

  

上午8:00

答案 2 :(得分:2)

AM / PM是大写的,您需要使用h指定一个小时数(需要hh两位数)。像,

LocalTime test = LocalTime.parse("8:00am".toUpperCase(), 
        DateTimeFormatter.ofPattern("h:mma"));

答案 3 :(得分:1)

你需要大写到AM并在8前面添加一个前导零。

LocalTime lt=LocalTime.parse("08:00AM",DateTimeFormatter.ofPattern("hh:mma"));

答案 4 :(得分:0)

请注意,在阿德莱德,要求使用AM,所以我必须在从文本解析之前将日期设为.toLowerCase()。因此,“ AM”失败了,“ am”起作用了。

答案 5 :(得分:0)

LocalTime lt=LocalTime.parse("08:00p.m.",DateTimeFormatter.ofPattern("hh:mma"));

如果您是上午或下午它可以工作,但是AM或PM无法工作。 我正在使用openjdk 11和openjdk 14,我认为这是一个错误。