SimpleDateFormat 24h

2022-09-01 05:33:47

我有一个解析为:SimpleDateFormatStringDate

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");

当我解析这个时:

format.parse("2011-08-29T12:44:00+0200");

结果将是,当使用时:Date.toLocaleString

2011年08月29日 00:44:00

当然,这应该是:

2011年8月29日 下午12:44:00

当我解析这个时:

format.parse("2011-08-29T13:44:00+0200");

然后结果如预期的那样:

2011年08月29日 13:44:00

我该如何解决这个问题?


答案 1

使用 HH 代替 hh 表示小时模式

H   Hour in day (0-23)  Number  0
k   Hour in day (1-24)  Number  24
K   Hour in am/pm (0-11)    Number  0
h   Hour in am/pm (1-12)    Number  12

答案 2

java.time through desugaring

我建议你使用java.time,现代Java日期和时间API,用于你的日期和时间工作。

您的字符串采用 ISO 8601 格式。为其定义格式化程序:

private static final DateTimeFormatter ISO_FORMATTER
        = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .appendOffset("+HHMM", "Z")
                .toFormatter(Locale.ROOT);

使用格式模式字符串可以更短,但我更喜欢重用内置的,它已经处理了ISO 8601。正如您的问题所证明的那样,编写格式模式字符串很容易出错。我还指定了根据ISO 8601,应接受与UTC的零偏移量(解析器也将接受)。ISO_LOCAL_DATE_TIMEZ+0000

解析如下:

    String isoString = "2011-08-29T12:44:00+0200";
    OffsetDateTime dateTime = OffsetDateTime.parse(isoString, ISO_FORMATTER);
    System.out.println(dateTime);

输出为:

2011-08-29T12:44+02:00

要获取为用户的区域设置设置格式化的字符串,请使用第二个格式化程序:

private static final DateTimeFormatter LOCALE_FORMATTER
        = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);

我们仍然不需要编写任何格式模式字符串。格式如下:

    String localeString = dateTime.format(LOCALE_FORMATTER);
    System.out.println(localeString);

输出正是它应该有的样子。我在区域设置中运行并得到:nl_NL

2011年8月29日 下午12:44:00

请跳过下一节。

如果我需要一个老式的怎么办?java.util.Date

没有人应该再使用这个类了。只有当您迫切需要一个您现在无法升级到java.time的旧版API时,请转换:DateDate

    Date oldfashionedDate = Date.from(dateTime.toInstant());
    System.out.println(oldfashionedDate);

有趣的是,输出将取决于时区。在我的时区,我得到了:

星期一 八月 29 12:44:00 CEST 2011

问:java.time 不需要 Android API 级别 26 吗?

java.time在较旧和较新的Android设备上都运行良好。它只需要至少Java 6

  • 在Java 8及更高版本以及较新的Android设备(从API级别26开始)中,现代API是内置的。
  • 在非Android Java 6和7中,获得ThreeTen Backport,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
  • 在较旧的Android上,要么使用desugaring,要么使用Android版本的ThreeTen Backport。它被称为ThreeTenABP。在后一种情况下,请确保从中导入带有子包的日期和时间类。org.threeten.bp

链接


推荐