Java时间是否正确处理了密歇根州的时区/夏令时历史?

时间:2019-01-18 22:06:46

标签: java-time

我偶然发现下面的图片,想知道: Java时间会正确反映密歇根州的时间顺序吗?

Image source

注意:美国的总体变更日期不一定与密歇根州采用这些变更的日期一致。

Chronology of Time Observance in Michigan

1 个答案:

答案 0 :(得分:0)

是的,密歇根州的时间历史由Java时间精心处理

我对Java时间在处理America/DetroitAmerica/Menominee的时间历史方面的精确性和复杂性印象深刻。似乎上述每种情况都得到了正确处理。我真诚地为Joda和Java时代的开发人员鼓掌,这是一件很棒的作品。

测试用例

下面是一组测试案例,用于练习上图中的场景。请注意,这里使用粗略的日期是为了简化,但是该库具有更高的精度。

@Test
public void dstHistoryInMichigan() {
  String detroitMeanTime = "-05:32:11";
  String menomineeMeanTime = "-05:50:27";
  String cst = "-06:00";
  String cdt = "-05:00";
  String centralWarTime = "-05:00";
  String est = "-05:00";
  String edt = "-04:00";
  String easternWarTime = "-04:00";

  assertThat(detroit(1883, 7, 30)).as("Detroit 1883").isEqualTo(detroitMeanTime);
  assertThat(menominee(1883, 7, 30)).as("Menominee 1883").isEqualTo(menomineeMeanTime);
  assertThat(detroit(1905, 2, 20)).as("Detroit 1905").isEqualTo(cst);
  assertThat(menominee(1905, 2, 20)).as("Menominee 1905").isEqualTo(cst);
  assertThat(detroit(1923, 1, 1)).as("Detroit 1923").isEqualTo(est);
  assertThat(menominee(1923, 1, 1)).as("Menominee 1923").isEqualTo(cst);
  assertThat(detroit(1937, 7, 30)).as("Detroit 1937").isEqualTo(est);
  assertThat(menominee(1937, 7, 30)).as("Menominee 1937").isEqualTo(cst);
  assertThat(detroit(1944, 7, 30)).as("Detroit 1944").isEqualTo(easternWarTime);
  assertThat(menominee(1944, 7, 30)).as("Menominee 1944").isEqualTo(centralWarTime);
  assertThat(detroit(1946, 7, 30)).as("Detroit 1946").isEqualTo(est);
  assertThat(menominee(1946, 1, 30)).as("Menominee 1946").isEqualTo(cst);
  assertThat(detroit(1966, 7, 30)).as("Detroit 1966").isEqualTo(est);
  assertThat(menominee(1966, 7, 30)).as("Menominee 1966").isEqualTo(est);
  assertThat(detroit(1967, 7, 30)).as("Detroit 1967").isEqualTo(est);
  assertThat(menominee(1967, 7, 30)).as("Menominee 1967").isEqualTo(cst);
  assertThat(detroit(1968, 7, 30)).as("Detroit 1968").isEqualTo(est);
  assertThat(menominee(1968, 7, 30)).as("Menominee 1968").isEqualTo(cst);
  assertThat(detroit(1973, 1, 30)).as("Detroit Jan 1973").isEqualTo(est);
  assertThat(detroit(1973, 7, 30)).as("Detroit Summer 1973").isEqualTo(edt);
  assertThat(detroit(1974, 1, 7)).as("Detroit Jan 1974").isEqualTo(edt);
  assertThat(detroit(1974, 7, 30)).as("Detroit Summer 1974").isEqualTo(edt);
  assertThat(detroit(1974, 10, 28)).as("Detroit Fall 1974").isEqualTo(est);
  assertThat(menominee(1974, 7, 30)).as("Menominee Summer 1974").isEqualTo(cdt);
  assertThat(menominee(1974, 10, 28)).as("Menominee Fall 1974").isEqualTo(cst);
  assertThat(detroit(1975, 3, 5)).as("Detroit March 1975").isEqualTo(est);
  assertThat(detroit(1975, 4, 28)).as("Detroit April 1975").isEqualTo(edt);
  assertThat(menominee(1975, 2, 5)).as("Menominee Feb 1975").isEqualTo(cst);
  assertThat(menominee(1975, 4, 28)).as("Menominee April 1975").isEqualTo(cdt);
  assertThat(detroit(1985, 4, 7)).as("Detroit April 1985").isEqualTo(est);
  assertThat(detroit(1987, 4, 7)).as("Detroit April 1987").isEqualTo(edt);
  assertThat(menominee(1985, 4, 7)).as("Menominee April 1985").isEqualTo(cst);
  assertThat(menominee(1987, 4, 7)).as("Menominee April 1987").isEqualTo(cdt);
  assertThat(detroit(2004, 3, 15)).as("Detroit March 2004").isEqualTo(est);
  assertThat(detroit(2007, 3, 15)).as("Detroit March 2007").isEqualTo(edt);
  assertThat(menominee(2004, 3, 15)).as("Menominee March 2004").isEqualTo(cst);
  assertThat(menominee(2007, 3, 15)).as("Menominee March 2007").isEqualTo(cdt);
}

private static final ZoneId menomineeTz = ZoneId.of("America/Menominee");
private static final ZoneId detroitTz = ZoneId.of("America/Detroit");

private String detroit(int year, int month, int day) {
  return getOffset(LocalDate.of(year, month, day), detroitTz);
}

private String menominee(int year, int month, int day) {
    return getOffset(LocalDate.of(year, month, day), menomineeTz);
}

private String getOffset(LocalDate date, ZoneId tz) {
  return date.atStartOfDay(tz).withZoneSameInstant(tz).getOffset().getId();
}