Java 时间解析“2021 年 6 月 26 日,纽约时间下午 04:30:15”

问题描述

我有一个像这样的字符串:

String str = "Jun 26th 2021,04:30:15 pm NY";

我想将其转换为 zoneddatetime,为此我使用 DateTimeFormatterBuilder

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .appendPattern("MMM dd'th' uuuu,h:mm:ss a z")
        .toFormatter(Locale.US);
zoneddatetime result = zoneddatetime.parse(str,formatter);

但是解析器对这种格式不满意我收到了这个错误

java.time.format.DateTimeParseException: Text 'Jun 26th 2021,04:30:15 pm NY' Could not be parsed at index 27

NY 似乎没有涵盖 z,请对此错误有任何想法,还有什么技巧可以避免解析器中的 'th' 吗?

解决方法

DateTimeFormatter#parse(CharSequence,ParsePosition) 随时为您服务。

请注意,NY 不是时区的名称。时区的命名约定是地区/城市,例如Europe/Paris。您可以使用 ZoneId#getAvailableZoneIds 获取时区名称列表。

此外,对于带序数的月份日期,例如26 日,您可以构建一个 Map,如下面的代码所示。

演示:

import java.text.ParsePosition;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        String strDateTime ="Jun 26th 2021,04:30:15 pm NY";
    
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .appendPattern("[MMMM][MMM] ") // caters for both full name and 3-letter abbv.
                .appendText(ChronoField.DAY_OF_MONTH,ordinalMap())
                .appendPattern(" u,h:m:s a")
                .toFormatter(Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.from(dtf.parse(strDateTime,new ParsePosition(0)));
        ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/New_York"));
        System.out.println(zdt);
    }
    static Map<Long,String> ordinalMap() {
        String[] suffix = { "th","st","nd","rd","th","th" };
        Map<Long,String> map = new HashMap<>();
        
        for (int i = 1; i <= 31; i++) 
            map.put((long)i,String.valueOf(i) + suffix[(i > 3 && i < 21) ? 0 : (i % 10)]);
        
        return map;
    }
}

输出:

2021-06-26T16:30:15-04:00[America/New_York]

ONLINE DEMO

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。

礼貌:构建 Map 的逻辑基于 this excellent answer

,

正如 Sweeper 所强调的,纽约不是 Java 认可的时区。为了尽量减少对代码的更改,您可以使用 DateTimeFormatter 格式化程序的 DateTimeFormatter#withZone 方法返回格式化程序的副本,其中包含新的覆盖区域,如下所示:

String str = "Jun 26th 2021,04:30:15 pm"; //<-- erased NY
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .appendPattern("MMM dd'th' uuuu,h:mm:ss a")
        .toFormatter(Locale.US);
ZonedDateTime result = ZonedDateTime.parse(str,formatter.withZone(ZoneId.of("America/New_York")));
System.out.println(result); //<-- 2021-06-26T16:30:15-04:00[America/New_York]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...