Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 轮班日期dst中的一小时_Java_Jodatime_Java.util.calendar - Fatal编程技术网

Java 轮班日期dst中的一小时

Java 轮班日期dst中的一小时,java,jodatime,java.util.calendar,Java,Jodatime,Java.util.calendar,我正在逐行处理一个文件 每行都有以下格式的日期:YYMMDD HHMM 该文件基本上每15分钟记录一次读数。录音使用的是所在时区的日光节约。我遇到的问题是在春季提前和倒退期间。记录是重复发生回退时的日期和发生回退时的间隔 回退示例: 1411020100 1411020115 1411020130 1411020145 14110200 141102 0115-重复 141102 0130-重复 141102 0145-重复 141102 0200-重复 弹簧前进示例: 1503080200 1

我正在逐行处理一个文件

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

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

回退示例:

1411020100

1411020115

1411020130

1411020145

14110200

141102 0115-重复

141102 0130-重复

141102 0145-重复

141102 0200-重复

弹簧前进示例:

1503080200

1503080315

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

我正在开发的程序目前正在使用java.util.Calendar。我曾尝试使用java日历进行轮班,但在添加日期方面遇到了很多问题。我假设问题是,它试图自己纠正DST问题,而我只想把日期改一个小时。它也有一个问题,检测差距。例如,它认为第一个1:15-2:00是在白天,而事实并非如此

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

回退示例:

1411020100无变化

141102 0115无变化

1411020130无变化

141102 0145无变化

141102 0200无变化

141102 0115至141102 0215

1411020130至1411020230

141102 0145至141102 0245

141102 0200至141102 0300

不断更改日期,直到它到达弹簧前进

1503080200至1503080300

150308 0315无变化

我尝试了很多方法,但似乎都没有找到解决办法。我并不反对使用乔达时间,因为我也一直在研究这个问题。任何帮助都将不胜感激,谢谢。

UTC 始终用于数据交换和此类读数日志。总是,总是,总是使用UTC。将UTC视为一个真实时间,将其他时区视为与UTC的偏差

顺便说一下,分区日期时间值并不是唯一需要担心的问题。其他异常发生在不同的时区,导致向前或向后移动。解决方案很简单:避开所有时区–使用UTC

Instant
Instant
类以UTC为单位以纳秒的分辨率捕获时间线上的一个时刻。这应该是你去上课的日期时间工作

Instant instant = Instant.now();
串 对于日志记录,生成标准格式的字符串。坚持使用经验证的ISO8601格式,而不是发明自己的格式

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

String output = instant.toString();
2016-11-02T21:10:05.321Z

并且一定要在日期中包含世纪
20
。省略只会为错误的解释创造很多机会。存储和内存真的很便宜,我们可以负担得起额外的两位数

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

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

解析字符串 下面是解析日期时间字符串的代码。我们首先解析,没有任何时区或偏移,因为您的输入缺少任何时区或偏移的指示符。然后我们分配一个时区来获得a,看看它如何处理DST转换的时刻

我假设您所讨论的时区使用的DST后退切换为凌晨2点。我用
America/Montreal
作为这样一个例子

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("");
}
但这是一个冒险的破解方案。我不确定这项工作,因为我还没有想清楚。如果不顾一切,也许你可以让它工作

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

UTC 始终用于数据交换和此类读数日志。总是,总是,总是使用UTC。将UTC视为一个真实时间,将其他时区视为与UTC的偏差

顺便说一下,分区日期时间值并不是唯一需要担心的问题。其他异常发生在不同的时区,导致向前或向后移动。解决方案很简单:避开所有时区–使用UTC

Instant
Instant
类以UTC为单位以纳秒的分辨率捕获时间线上的一个时刻。这应该是你去上课的日期时间工作

Instant instant = Instant.now();
串 对于日志记录,生成标准格式的字符串。坚持使用经验证的ISO8601格式,而不是发明自己的格式

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

String output = instant.toString();
2016-11-02T21:10:05.321Z

并且一定要在日期中包含世纪
20
。省略只会为错误的解释创造很多机会。存储和内存真的很便宜,我们可以负担得起额外的两位数

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

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

解析字符串 下面是解析日期时间字符串的代码。我们首先解析,没有任何时区或偏移,因为您的输入缺少任何时区或偏移的指示符。然后我们分配一个时区来获得a,看看它如何处理DST转换的时刻

我假设您所讨论的时区使用的DST后退切换为凌晨2点。我用了
美国/蒙特利尔March, 29 2015 at 2:00:00 A.M. clocks were turned forward 1 hour to
March, 29 2015 at 3:00:00 A.M. local daylight time instead
(So a time like March, 29 2015 2:30:00 A.M. didn't actually exist!)

October, 25 2015 at 3:00:00 A.M. clocks were turned backward 1 hour to
October, 25 2015 at 2:00:00 A.M. local daylight time instead
(So a time like October, 25 2015 2:30:00 A.M. actually existed twice!)
LocalDateTime ldt = LocalDateTime.of(2015, 3, 29, 2, 30);
System.out.println(ldt);
2015-03-29T02:30
ZonedDateTime zdt = ZonedDateTime.of(
     2015, 3, 29, 2, 30, 0, 0, ZoneId.of("Europe/Rome"));
System.out.println(zdt);
2015-03-29T03:30+02:00[Europe/Rome]
ZonedDateTime zdt1 = ZonedDateTime.of(
     2015, 3, 29, 2, 30, 0, 0, ZoneOffset.ofHours(2));
ZonedDateTime zdt2 = ZonedDateTime.of(
     2015, 3, 29, 2, 30, 0, 0, ZoneId.of("UTC+2"));
System.out.println(zdt1); System.out.println(zdt2);
2015-03-29T02:30+02:00[UTC+02:00] 2015-03-29T02:30+02:00
ZonedDateTime zdt = ZonedDateTime.of(
    2015, 10, 25, 2, 30, 0, 0, ZoneId.of("Europe/Rome"));
ZonedDateTime zdt2 = zdt.plusHours(1);
System.out.println(zdt);
System.out.println(zdt2);
2015-10-25T02:30+02:00[Europe/Rome] 2015-10-25T02:30+01:00[Europe/Rome]
ZonedDateTime zdt = ZonedDateTime.of(
    2015, 3, 29, 1, 0, 0, 0, ZoneId.of("Europe/Rome"));
System.out.println(zdt.plus(Duration.ofDays(1)));
2015-03-30T02:00+02:00[Europe/Rome]
System.out.println(zdt.plus(Period.ofDays(1)));
2015-03-30T01:00+02:00[Europe/Rome]
LocalDateTime localDateTimeBeforeDST = LocalDateTime
  .of(2018, 3, 25, 1, 55);

assertThat(localDateTimeBeforeDST.toString())
  .isEqualTo("2018-03-25T01:55");
ZoneId italianZoneId = ZoneId.of("Europe/Rome");
ZonedDateTime zonedDateTimeBeforeDST = localDateTimeBeforeDST
  .atZone(italianZoneId);

assertThat(zonedDateTimeBeforeDST.toString())
  .isEqualTo("2018-03-25T01:55+01:00[Europe/Rome]"); 
ZonedDateTime zonedDateTimeAfterDST = zonedDateTimeBeforeDST
  .plus(10, ChronoUnit.MINUTES);

assertThat(zonedDateTimeAfterDST.toString())
  .isEqualTo("2018-03-25T03:05+02:00[Europe/Rome]");
Long deltaBetweenDatesInMinutes = ChronoUnit.MINUTES
  .between(zonedDateTimeBeforeDST,zonedDateTimeAfterDST);
assertThat(deltaBetweenDatesInMinutes)
  .isEqualTo(10);