夏令时时移班一小时 [英] Shift date an hour when in dst

查看:98
本文介绍了夏令时时移班一小时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在逐行处理文件.

每行的日期都采用以下格式:YYMMDD HHMM

Each line has a date in the following format: YYMMDD HHMM

文件基本上每15分钟记录一次读数.录制使用的是所在时区的日光节约.我遇到的问题是春季提前和后退.记录是在发生回退时复制日期,并在发生回退时复制间隔.

The file is basically recording a reading every 15 minutes. The recording is using day light savings for the time zone it is in. The issue I am having is during spring ahead and fall back. The recording is duplicating dates when fall back occurs and a gap when fall back occurs.

回退示例:

141102 0100

141102 0100

141102 0115

141102 0115

141102 0130

141102 0130

141102 0145

141102 0145

141102 0200

141102 0200

141102 0115-重复

141102 0115 - duplicate

141102 0130-重复

141102 0130 - duplicate

141102 0145-重复

141102 0145 - duplicate

141102 0200-重复

141102 0200 - duplicate

春季向前的例子:

150308 0200

150308 0200

150308 0315

150308 0315

我需要做的是,在夏时制时将所有日期向前移动一个小时.

What I need to be able to do, is shift all the dates forward an hour when in daylight savings time.

我正在处理的程序当前正在使用java.util.Calendar.我已经尝试过使用Java日历进行轮班,并且在添加日期时遇到了很多问题.我想的问题是,当我要做的只是将日期偏移一个小时时,它本身正在尝试纠正DST问题.在检测该差距方面也存在问题.例如,它认为第一个1:15-2:00是白天,而事实并非如此.

The program I am working on is using java.util.Calendar currently. I have tried doing the shift using the java Calendar and am running into lots of issues with adding the dates. I assume the problem to be that it is trying to correct DST issues itself, when all I want to do is shift the date by an hour. It also has an issue with detecting that gap. For example it thinks that the first 1:15 - 2:00 is in daylight time, when this is not the case for it.

基本上我想要的是将后备示例更改为该日期范围内的所有内容,以后退一小时:

Basically what I want is to change the fallback example to everything that falls in this date range to shift back an hour:

回退示例:

141102 0100不变

141102 0100 no change

141102 0115不变

141102 0115 no change

141102 0130不变

141102 0130 no change

141102 0145不变

141102 0145 no change

141102 0200不变

141102 0200 no change

141102 0115至141102 0215

141102 0115 to 141102 0215

141102 0130至141102 0230

141102 0130 to 141102 0230

141102 0145至141102 0245

141102 0145 to 141102 0245

141102 0200至141102 0300

141102 0200 to 141102 0300

继续更改日期,直到春天来临

Keeps on changing date until it hits the spring forward

150308 0200至150308 0300

150308 0200 to 150308 0300

150308 0315没有变化.

150308 0315 no change.

我尝试了很多方法,但似乎无法解决.我也不反对使用Joda Time,因为我也一直在研究这一点.任何帮助将不胜感激,谢谢.

I have tried lots of ways, and can't seem to come to a solution. I am not opposed to using Joda Time as I've been looking into that a bit as well. Any help would be appreciated, thanks.

推荐答案

UTC

始终使用 UTC 进行数据交换和这种读数日志.始终,始终,始终使用UTC.将UTC视为一个真实时间,而将其他时区视为与UTC的偏差.

UTC

Always use UTC for data exchange and this kind of readings log. Always, always, always use UTC. Think of UTC as the One True Time and other time zones as deviations from UTC.

顺便说一句,夏令时(DST)不是 >分区日期时间值唯一需要担心的问题.其他异常会在各个时区发生,导致壁钟时间向前或向后移动.解决方案很简单:避免使用所有时区– 使用UTC .

By the way, Daylight Saving Time (DST) is not the only problem to worry about with zoned date-time values. Other anomalies occur in various time zones resulting in wall-clock time shifting forward or backward. The solution is easy: Avoid all time zones – Use UTC.

Instant类捕获UTC时间轴上的时刻,分辨率为纳秒.这应该是您上班的日期时间工作.

The Instant class captures a moment on the timeline in UTC with a resolution of nanoseconds. This should be you go-to class for date-time work.

Instant instant = Instant.now();

字符串

要进行记录,请生成标准 ISO 8601 格式的字符串.坚持使用经过验证的ISO 8601格式,而不要发明自己的格式.

Strings

For logging, generate a string in standard ISO 8601 format. Stick with the proven ISO 8601 formats rather than invent your own.

包括Instant在内的java.time类在解析/生成字符串时默认使用ISO 8601格式.因此,无需指定格式化模式.

The java.time classes including Instant use ISO 8601 formats by default when parsing/generating strings. So no need to specify formatting patterns.

String output = instant.toString();

2016-11-02T21:10:05.321Z

2016-11-02T21:10:05.321Z

Instant instant = Instant.parse( "2016-11-02T21:10:05.321Z" );

并且始终在您的日期中包含世纪20.遗漏只是为误解中的错误创造了很多机会.存储和内存确实足够便宜,我们可以负担两个额外的数字.

And always include the century 20 in your dates. Omitting just creates so much opportunity for errors in misinterpreting. Storage and memory really is cheap enough that we can afford the two extra digits.

始终在您的序列化日期时间值中包含时区或UTC偏移量指示符.

Always include a time zone or offset-from-UTC indicator with your serialized date-time values.

在上面看到的Instant::toString结果中,Z代表Zulu,表示UTC.

In the Instant::toString result seen above, the Z stands for Zulu which means UTC.

这里是解析您的日期时间字符串的代码.我们首先解析为 LocalDateTime 任何时区或偏移量,因为您的输入缺少任何时区或偏移量指示符.然后,我们分配一个时区以获取 ZonedDateTime ,以了解如何处理DST转换的瞬间.

Here is code to parse your date-time strings. We parse as LocalDateTime first, without any time zone or offset, because your input lacks any indicator of time zone or offset. Then we assign a time zone to get a ZonedDateTime, to see how it handles the moment of DST cut-over.

我假设您所涉及的时区使用DST后备切换时间凌晨2点.我以America/Montreal为例.

I assume your time zone in question uses a DST fall-back cutover of 2 AM. I used America/Montreal as an example of such.

List<String> inputs = new ArrayList<>( 2 );
inputs.add( "141102 0115" );  // 1 AM
inputs.add( "141102 0215" );  // 2 AM

for( String input : inputs ) {
    DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuMMdd HHmm" );
    LocalDateTime ldt = LocalDateTime.parse( input , f );

    // At 2 AM in this zone, the clock falls back one hour for DST cutover. The 1 AM hour repeats.
    ZoneId z = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = ldt.atZone( z );

    System.out.println( "input: " + input );
    System.out.println( "ldt: " + ldt );
    System.out.println( "zdt: " + zdt );
    System.out.println( "instant: " + zdt.toInstant() );
    System.out.println("");
}

输入:141102 0115

input: 141102 0115

ldt:2014-11-02T01:15

ldt: 2014-11-02T01:15

zdt:2014-11-02T01:15-04:00 [美国/蒙特利尔]

zdt: 2014-11-02T01:15-04:00[America/Montreal]

即时:2014-11-02T05:15:00Z

instant: 2014-11-02T05:15:00Z

…和…

输入:141102 0215

input: 141102 0215

ldt:2014-11-02T02:15

ldt: 2014-11-02T02:15

zdt:2014-11-02T02:15-05:00 [美国/蒙特利尔]

zdt: 2014-11-02T02:15-05:00[America/Montreal]

即时:2014-11-02T07:15:00Z

instant: 2014-11-02T07:15:00Z

您可以在IdeOne.com中实时查看此代码.请注意UTC值(Z)的两个小时差异.

You can see this code live in IdeOne.com. Note the two hour difference in UTC values (Z).

我们看到的行为已记录在案.

The behavior we see is documented.

在大多数情况下,本地日期时间只有一个有效偏移量.在重叠的情况下,将时钟调回,则有两个有效的偏移量.此方法使用通常对应于夏季"的更早偏移量.

In most cases, there is only one valid offset for a local date-time. In the case of an overlap, where clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".

在1:15 AM模棱两可的情况下,可能是第一次出现,也可能是第二次出现,java.time与第一次出现一起出现.

Where the 1:15 AM is ambiguous, could be either the first or second occurrence, java.time goes with the first.

您可以玩猜谜游戏来尝试调整这些设计欠佳的琴弦.如果确定每个时钟小时内至少有一个样本,则可以跟踪先前的样本,并查看正在处理的样本的时钟时间是否早于先前的时间.如果是这样,您可以假定这是DST后备转换,并使用plusHours( 1 )添加一个小时.

You could play a guessing-game to try to adjust these poorly-designed strings. If you are sure you have at least one sample during every clock hour, you could keep track of previous samples and see if the sample being processed has a clock-time earlier than the previous. If so you could assume this is a DST fall-back cutover, and add an hour with plusHours( 1 ).

if( processingZdt.toLocalDateTime().isBefore( previousZdt.toLocalDateTime() ) { 
    processingZdt.plusHours( 1 ) ;  // A hack; I am *not* recommending this.
    …

但这是一个危险的解决方案.我不确定这项工作,因为我还没有仔细考虑.如果不顾一切,也许您可​​以使它工作.

But this is a risky hack of a solution. I'm not sure this work, as I've not thought it through. If desperate, perhaps you can make it work.

最明智的方法是预防:使用UTC .

The much wise approach is prevention: Use UTC.

这篇关于夏令时时移班一小时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆