squ*_*uck 4 java timezone datetime-parsing java-8 java-time
假设我有一个日期,例如:
2013年11月30日19:00:00.001930000东部标准时间
我试图解析使用输入DateTimeFormatterBuilder,但我想不出该怎么把为Set通用类型ZoneId是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();
Run Code Online (Sandbox Code Playgroud)
正如班级文件简要解释一样,主流媒体中常见的3-4个字母表示时区并不是官方时区.这些伪区域不是标准化的,甚至不是唯一的!许多代码在全球范围内重复使用.例如,IST印度标准时间和爱尔兰标准时间都是.并且CST是中国标准时间和中央标准时间(在北美).
切勿使用这些伪区域.指定适当的时区名称,格式continent/region,如America/Montreal,Africa/Casablanca或Pacific/Auckland.
如果您的输入确实具有这些伪区域,则采用缩写格式,您必须处理歧义.默认情况下,格式化程序构建器将尝试通过考虑Locale格式化程序来解决歧义.在的情况下CST,如果Locale是Locale.CHINA,那么也许CST指中国标准时间,而不是中部标准时间.
不幸的是,这是一种粗暴的做法 问题Locale和时区是正交的.您可以让一个说汉语的用户处理芝加哥的交货数据,在这种情况下,Locale可能是中国,但CST数据中的数据是中央标准时间.因此,在这种情况下,您可以指定一个或多个时区,例如格式化程序在尝试解析时要考虑America/Chicago并America/Winnipeg考虑CST的默认值Locale.
Set< ZoneID > zones = new TreeSet<>() ;
zones.add( ZoneId.of( "America/Chicago" ) ;
zones.add( ZoneId.of( "America/Manitoba" ) ;
…
.appendZoneText( TextStyle.SHORT , zones )
…
Run Code Online (Sandbox Code Playgroud)
这是一个完整的示例,解析CST为我的macOS MacBook上的中央标准时间设置为默认时区America/Los_Angeles和默认语言环境Locale.US.请注意,我们只传递一个参数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 );
Run Code Online (Sandbox Code Playgroud)
输入日期:2013年11月30日19:00:00.001930000 CST
zdt.toString():2013-11-30T19:00:00.001930-06:00 [美国/芝加哥]
让我们传递Set的ZoneId对象来重写该行为,暗示CST手段China Standard Time.在这里,我们就传递Set的ZoneId对象.我们使用相同的输入来获得非常不同的输出.
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 );
Run Code Online (Sandbox Code Playgroud)
输入日期:2013年11月30日19:00:00.001930000 CST
zdt.toString():2013-11-30T19:00:00.001930 + 08:00 [亚洲/上海]
现在,在您的情况下,您具有伪区域的全名而不是缩写.所以可能没有歧义.因此,您可能可以使用重载方法而不是第二个参数.
.appendZoneText( TextStyle.FULL )
Run Code Online (Sandbox Code Playgroud)
例:
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 );
Run Code Online (Sandbox Code Playgroud)
输入日期:2013年11月30日19:00:00.001930000东部标准时间
zdt.toString():2013-11-30T19:00:00.001930-05:00 [America/New_York]
然而,有是一个有用到传递Set的ZoneId对象也在这里.的Set是在分配的时区来实例化的使用ZonedDateTime对象.请注意上面输出中America/New_York默认分配的内容.但是还有许多其他时区也被伪区"东部标准时间"所暗示,例如巴哈马,America/Nassau墨西哥的坎昆等等.
然而,选择应用集合中的哪个元素对我来说是一个谜.我尝试使用SortedSet思维,可以选择在Set的自然顺序中找到的第一个.唉,ZoneId没有实现Comparable接口,所以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 );
Run Code Online (Sandbox Code Playgroud)
输入日期:2013年11月30日19:00:00.001930000东部标准时间
zdt.toString():2013-11-30T19:00:00.001930-06:00 [America/Cancun]
| 归档时间: |
|
| 查看次数: |
740 次 |
| 最近记录: |