gpt4 book ai didi

具有详细时区的 Java DateTimeFormatterBuilder

转载 作者:搜寻专家 更新时间:2023-11-01 02:01:04 25 4
gpt4 key购买 nike

假设我有一个日期,例如:

Nov 30, 2013 19:00:00.001930000 Eastern Standard Time

我正在尝试使用 DateTimeFormatterBuilder 解析输入, 但我无法弄清楚要为通用类型 ZoneIdSet 放什么这是下面的 null

String basePattern = "MMM dd, yyyy HH:mm:ss";
new DateTimeFormatterBuilder()
.appendPattern(basePattern)
.appendFraction(ChronoField.NANO_OF_SECOND,0,9, true)
.appendZoneText(TextStyle.FULL, null)
.toFormatter();

最佳答案

伪区

作为class documentation简单解释一下,主流媒体上常见的表示时区的3-4个字母实际上并不是官方时区。这些伪区不规范,甚至不唯一!许多代码在全局范围内重复使用。例如,IST 是印度标准时间和爱尔兰标准时间。 CST 既是中国标准时间又是Central Standard Time (在北美)。

切勿使用这些伪区域。指定 proper time zone name格式为continent/region,如America/Montreal , Africa/Casablanca ,或 太平洋/奥克兰

解决歧义

如果您的输入确实有这些伪区域,在缩写格式中,您必须处理歧义。默认情况下,格式化程序构建器将尝试通过考虑格式化程序的 Locale 来解决歧义。在 CST 的情况下,如果 LocaleLocale.CHINA,那么CST可能是指中国标准时间而不是中部标准时间。

不幸的是,这是一种粗略的方法。 Locale 和时区的问题是正交的。您可以让讲中文的用户处理芝加哥的交付数据,在这种情况下 Locale可能是中国,但数据中的 CST 表示 Central Standard Time .所以在这种情况下,您可以指定一个或多个时区,例如 America/ChicagoAmerica/Winnipeg格式化程序在尝试解析 CST 以覆盖考虑 Locale 的默认值时考虑。

Set< ZoneID > zones = new TreeSet<>() ;
zones.add( ZoneId.of( "America/Chicago" ) ;
zones.add( ZoneId.of( "America/Manitoba" ) ;

.appendZoneText( TextStyle.SHORT , zones )

这是一个完整的示例,将 CST 解析为我的 macOS MacBook 上的中央标准时间设置为 America/Los_Angeles 的默认时区和 Locale 的默认区域设置.美国。请注意,我们仅向 appendZoneText 传递了一个参数(未传递 Set)。

String input = "Nov 30, 2013 19:00:00.001930000 CST";  
String basePattern = "MMM dd, yyyy HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder( )
.appendPattern( basePattern )
.appendFraction( ChronoField.NANO_OF_SECOND , 0 , 9 , true )
.appendPattern( " " )
.appendZoneText( TextStyle.SHORT )
.toFormatter( );

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

System.out.println( "input: " + input );
System.out.println( "zdt.toString(): " + zdt );

input: Nov 30, 2013 19:00:00.001930000 CST

zdt.toString(): 2013-11-30T19:00:00.001930-06:00[America/Chicago]

让我们传递 ZoneId 对象的 Set 来覆盖该行为,暗示 CST 表示 中国标准时间 .在这里,我们确实传递了 ZoneId 对象的 Set。我们使用相同的输入来获得截然不同的输出。

Set < ZoneId > zones = new HashSet <>( );
zones.add( ZoneId.of( "Asia/Shanghai" ) ) ;

String input = "Nov 30, 2013 19:00:00.001930000 CST";
String basePattern = "MMM dd, yyyy HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder( )
.appendPattern( basePattern )
.appendFraction( ChronoField.NANO_OF_SECOND , 0 , 9 , true )
.appendPattern( " " )
.appendZoneText( TextStyle.SHORT , zones )
.toFormatter( );

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

System.out.println( "input: " + input );
System.out.println( "zdt.toString(): " + zdt );

input: Nov 30, 2013 19:00:00.001930000 CST

zdt.toString(): 2013-11-30T19:00:00.001930+08:00[Asia/Shanghai]

现在,在您的情况下,您拥有伪区域的全名而不是缩写。所以很可能没有歧义。所以你可能可以逃脱 overloaded method not taking a second argument .

.appendZoneText( TextStyle.FULL ) 

例子:

String input = "Nov 30, 2013 19:00:00.001930000 Eastern Standard Time";  
String basePattern = "MMM dd, yyyy HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder( )
.appendPattern( basePattern )
.appendFraction( ChronoField.NANO_OF_SECOND , 0 , 9 , true )
.appendPattern( " " )
.appendZoneText( TextStyle.FULL )
.toFormatter( );

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

System.out.println( "input: " + input );
System.out.println( "zdt.toString(): " + zdt );

input: Nov 30, 2013 19:00:00.001930000 Eastern Standard Time

zdt.toString(): 2013-11-30T19:00:00.001930-05:00[America/New_York]

不过, 也可以在此处传递 ZoneId 对象的 SetSet 用于将时区分配给实例化的 ZonedDateTime 对象。请注意,在上面的输出中,默认分配了 America/New_York。但还有许多其他时区也被伪时区“东部标准时间”所隐含,例如巴哈马、美国/拿骚、墨西哥的坎昆等。

然而,选择应用集合中的哪个元素对我来说是个谜。我尝试使用 SortedSet 认为可以选择在 Set 的自然顺序中找到的第一个。唉,ZoneId 没有实现 Comparable 接口(interface),因此不能使用 SortedSet,例如 TreeSet

Set < ZoneId > zones = new HashSet <>( );
zones.add( ZoneId.of( "America/Detroit" ) );
zones.add( ZoneId.of( "America/New_York" ) );
zones.add( ZoneId.of( "America/Nassau" ) );
zones.add( ZoneId.of( "America/Cancun" ) );

String input = "Nov 30, 2013 19:00:00.001930000 Eastern Standard Time";
String basePattern = "MMM dd, yyyy HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder( )
.appendPattern( basePattern )
.appendFraction( ChronoField.NANO_OF_SECOND , 0 , 9 , true )
.appendPattern( " " )
.appendZoneText( TextStyle.FULL , zones )
.toFormatter( );

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

System.out.println( "input: " + input );
System.out.println( "zdt.toString(): " + zdt );

input: Nov 30, 2013 19:00:00.001930000 Eastern Standard Time

zdt.toString(): 2013-11-30T19:00:00.001930-06:00[America/Cancun]

关于具有详细时区的 Java DateTimeFormatterBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46841729/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com