Java 使用带有时区的Joda解析日期
我有两个时间戳,它们以两种不同的格式描述同一时刻Java 使用带有时区的Joda解析日期,java,datetime,date,timezone,jodatime,Java,Datetime,Date,Timezone,Jodatime,我有两个时间戳,它们以两种不同的格式描述同一时刻 2010-10-0318:58:07和2010-10-03T16:58:07.000+02:00 我使用两个不同的日期格式化程序和Joda Time解析时间戳。最后,我希望有两个DateTime对象,它们在时间的同一瞬间是相等的 DateFormatter提供了几种控制时区和地区的方法,但我无法让它工作 这是我想使用的代码: final String date1 = "2010-10-03 18:58:07"; // Europe/Ber
2010-10-0318:58:07
和2010-10-03T16:58:07.000+02:00
我使用两个不同的日期格式化程序和Joda Time解析时间戳。最后,我希望有两个DateTime对象,它们在时间的同一瞬间是相等的
DateFormatter提供了几种控制时区和地区的方法,但我无法让它工作
这是我想使用的代码:
final String date1 = "2010-10-03 18:58:07"; // Europe/Berlin local time
final DateTimeFormatter formatter1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
final DateTime dateTime1 = formatter1.parseDateTime(date1);
final String date2 = "2010-10-03T16:58:07.000+02:00"; // Europe/Berlin local time with time zone
final DateTimeFormatter formatter2 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
final DateTime dateTime2 = formatter2.parseDateTime(date2);
Assert.assertTrue(dateTime1.isEqual(dateTime2));
如果您的默认时间僵尸是欧洲/柏林,则2010-10-03 18:58:07对应于2010-10-03T16:58:07.000+00:00
您可能误解了字符串表示法中的时区字段。你的时间戳2010-10-03T16:58:07.000+02:00意味着“它是16:58:07,在一个时区,与格林尼治标准时间的偏移量为+2小时),或者用另一种措辞来说,“现在柏林是16:58:07”。我想你希望它是指格林尼治标准时间16:58:07?你的两个时间戳在时间上并不代表同一个瞬间(正如jambjo已经说过的那样).见维基百科 另请参阅有关其工作原理的文档。如果您不提供任何时区,则将应用默认时区(如果您在柏林,则为柏林时区UTC+2)。因此:
变为2010-10-03 18:58:07
(柏林的18:58与UTC的偏移为2小时,即UTC的16:58)2010-10-03T18:58:07.000+02:00
保持原样,因为提供了一个时区(即柏林的16:58与UTC的偏移为2小时,即UTC的14:58)2010-10-03T16:58:07.000+02:00
希望您能理解。您需要使用该方法调整时间以获得所需的结果。我遇到了与您相同的问题,我发现的最佳方法是解析数据。 我最初的格式是:2018-01-22 09:25:14.000+0000 只需选择列并单击数据选项卡中的“文本到列” 我使用带空格的分隔符在3个不同的列中解析此格式。 所以在最后,我有 Col A 2018-01-22 Col B 09:25:14.000 C+0000列tl;dr 使用取代Joda time的现代java.time类 真的 细节 这是正确的,因为您误解了和值的含义 现在在2018年,该项目处于维护模式。该项目的主要作者斯蒂芬·科尔伯恩(Stephen Colebourne)继续发现并编写了其实现,即在中发现的类 首次输入
你的输入字符串<代码> 201010-03 18:58:07 几乎是标准格式。要遵守,用“<代码> T < /代码>替换中间的空间。
String input1 = "2010-10-03 18:58:07".replace( " " , "T" ) ;
该字符串缺少时区或UTC偏移量的任何指示符。因此将其解析为LocalDateTime
LocalDateTime ldt = LocalDateTime.parse( input1 ) ;
此值不代表某个时刻,也不是时间线上的某个点。如果没有区域或偏移的上下文,它可能是全球时区范围内约26-27小时内的任意时刻
在您的评论中,您发现输入字符串显然是用来表示欧洲/莫斯科
时区中的日期和时间。因此,我们可以指定该区域来确定时间线上的某个时刻和点
ZoneId zMoscow = ZoneId.of( "Europe/Moscow" ) ;
ZonedDateTime zdtMoscow = ldt.atZone( zMoscow ) ; // Determine a moment by assigning a time zone.
zdtMoscow.toString():2010-10-03T18:58:07+04:00[欧洲/莫斯科]
第二输入
您的第二次输入符合标准格式
此输入与UTC的偏移量比UTC提前两小时。因此,此字符串表示UTC中14:58:07的时间
我们可以解析为一个OffsetDateTime
,以尊重给定的偏移量
OffsetDateTime odt2 = OffsetDateTime.parse( "2010-10-03T16:58:07.000+02:00" ) ;
odt2.toString():2010-10-03T16:58:07+02:00
比较
这两个输入是否代表同一时刻,时间线上的同一点
比较的一种方法是将两者都调整为UTC。根据定义,即时
始终为UTC
提示:养成思考、工作、存储、交换和登录UTC的习惯。将UTC视为一个真实的时间
运行时,我们看到的结果末尾有一个Z
。这意味着UTC,发音为Zulu
。事实上,我们看到这两个值代表同一时刻,UTC时间几乎为下午3点
instant1.toString():2010-10-03T14:58:07Z
instant2.toString():2010-10-03T14:58:07Z
平等:真的
关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,如,& 该项目现已启动,建议迁移到类 要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和解释。规范为 您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*
classes
从哪里获得java.time类
- 、和更高版本-标准Java API的一部分,带有捆绑实现。
- Java9添加了一些次要功能和修复
- 及
- 大多数java.time功能都在中向后移植到Java6和Java7
-
- 更高版本的Android捆绑包实现了java.time类
- 对于早期的Android(您在“2010-10-03T16:58:07.000+02:00”中有一个类型,表示它不是位于与格林尼治标准时间偏移+2小时的时区中的16:58:07)”。该类型必须为:“2010-10-03T16:58:07.000+02:00表示它位于与UTC偏移+2小时的时区中)“是的,我预计是格林威治标准时间16:58:07。然后,时间戳似乎被打破了。这些是来自不同服务器的两个不同日志文件的时间戳。我很确定他们指定了相同的事件。这就是我的困惑所在。@MacSim:当然,我在那里写得有点太快了。当我们想到在欧洲/莫斯科时区t生成的第一个时间戳时,这一切都是有道理的
OffsetDateTime odt2 = OffsetDateTime.parse( "2010-10-03T16:58:07.000+02:00" ) ;
Instant instant1 = zdtMoscow.toInstant() ; // Adjust from time zone to UTC. Instant instant2 = odt2.toInstant() ; // Adjust from offset to UTC. boolean equality = instant1.equals( instant2 );