gpt4 book ai didi

java - 非 DST 时区的 Joda 时间转换不正确

转载 作者:搜寻专家 更新时间:2023-11-01 02:54:06 26 4
gpt4 key购买 nike

我遇到了 Joda 问题,我认为这可能是一个错误。然而,我很可能在使用库时犯了错误,所以请给我你的反馈。

我们一直在生产中使用 joda 在我们的数据库存储格式 (UTC) 和用户的时区偏好之间转换时间。使用该系统的员工都在不遵守夏令时的亚利桑那州工作。除其他外,该系统跟踪全国体育赛事的开始时间。

Joda 对我们来说工作得很好,直到我们注意到在时间更改的前一天我们得到了一些不正确的结果。我们发现 joda 似乎在 UTC 午夜改为夏令时,而不是在特定时区的适当时间。此外,仅当将 DST 观察状态之间的时间转换为非 DST 状态(如亚利桑那州)时,才会出现此问题。

我制作了一个完整的测试用例来说明这个问题。正如您将看到的,joda 为所有 US/Eastern -> US/Pacific 测试用例提供了预期的结果。对于 US/Arizona -> US/Pacific,它在 11 月变化之前和之后的全年都有效。然而,在时间更改当天(11 月 6 日),时间不正确。行军时间的变化也可能存在问题,但我还没有对其进行详尽的测试。

这是所提供测试的输出(11 月 6 日的条目说明了错误):

=== November 1st, Expected Result (0 hour) ===
java:
Converting 2010-11-01 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-01 09:00. Change (0 hour).

joda:
Converting 2010-11-01 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-01 09:00. Change (0 hour).

=======================================

=== November 6th, Expected Result (0 hour) ===
java:
Converting 2010-11-06 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-06 09:00. Change (0 hour).

joda:
Converting 2010-11-06 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-06 08:00. Change (-1 hour).

=======================================

=== November 12th, Expected Result (-1 hour) ===
java:
Converting 2010-11-12 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-12 08:00. Change (-1 hour).

joda:
Converting 2010-11-12 09:00 from US/Arizona to US/Pacific.
Result: 2010-11-12 08:00. Change (-1 hour).

=======================================

=== March 12th, Expected Result (-1 hour) ===
java:
Converting 2010-03-12 09:00 from US/Arizona to US/Pacific.
Result: 2010-03-12 08:00. Change (-1 hour).

joda:
Converting 2010-03-12 09:00 from US/Arizona to US/Pacific.
Result: 2010-03-12 08:00. Change (-1 hour).

=======================================

=== March 14th, Expected Result (0 hour) ===
java:
Converting 2010-03-14 09:00 from US/Arizona to US/Pacific.
Result: 2010-03-14 09:00. Change (0 hour).

joda:
Converting 2010-03-14 09:00 from US/Arizona to US/Pacific.
Result: 2010-03-14 09:00. Change (0 hour).

=======================================

=== November 1st, Expected Result (-3 hour) ===
java:
Converting 2010-11-01 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-01 06:00. Change (-3 hour).

joda:
Converting 2010-11-01 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-01 06:00. Change (-3 hour).

=======================================

=== November 6th, Expected Result (-3 hour) ===
java:
Converting 2010-11-06 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-06 06:00. Change (-3 hour).

joda:
Converting 2010-11-06 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-06 06:00. Change (-3 hour).

=======================================

=== November 12th, Expected Result (-3 hour) ===
java:
Converting 2010-11-12 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-12 06:00. Change (-3 hour).

joda:
Converting 2010-11-12 09:00 from US/Eastern to US/Pacific.
Result: 2010-11-12 06:00. Change (-3 hour).

=======================================

=== March 12th, Expected Result (-3 hour) ===
java:
Converting 2010-03-12 09:00 from US/Eastern to US/Pacific.
Result: 2010-03-12 06:00. Change (-3 hour).

joda:
Converting 2010-03-12 09:00 from US/Eastern to US/Pacific.
Result: 2010-03-12 06:00. Change (-3 hour).

=======================================

=== March 14th, Expected Result (-3 hour) ===
java:
Converting 2010-03-14 09:00 from US/Eastern to US/Pacific.
Result: 2010-03-14 06:00. Change (-3 hour).

joda:
Converting 2010-03-14 09:00 from US/Eastern to US/Pacific.
Result: 2010-03-14 06:00. Change (-3 hour).

=======================================

这是完整的测试用例:

package com.test.time;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.joda.time.DateTimeZone;
import org.junit.Before;
import org.junit.Test;

public class TimeTest {
Calendar nov6;
Calendar nov1;
Calendar nov12;

Calendar mar12;
Calendar mar14;

@Before
public void doBefore() {
// November 1st 2010, 9:00pm (DST is active)
nov1 = Calendar.getInstance();
nov1.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
nov1.set(Calendar.HOUR_OF_DAY, 21);
nov1.set(Calendar.MINUTE, 0);
nov1.set(Calendar.SECOND, 0);
nov1.set(Calendar.YEAR, 2010);
nov1.set(Calendar.MONTH, 10); // November
nov1.set(Calendar.DATE, 1);

// November 6st 2010, 9:00pm (DST is still active until early AM
// november 7th)
nov6 = Calendar.getInstance();
nov6.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
nov6.set(Calendar.HOUR_OF_DAY, 21);
nov6.set(Calendar.MINUTE, 0);
nov6.set(Calendar.SECOND, 0);
nov6.set(Calendar.YEAR, 2010);
nov6.set(Calendar.MONTH, 10); // November
nov6.set(Calendar.DATE, 6);

// November 12th 2010, 9:00pm (DST has ended)
nov12 = Calendar.getInstance();
nov12.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
nov12.set(Calendar.HOUR_OF_DAY, 21);
nov12.set(Calendar.MINUTE, 0);
nov12.set(Calendar.SECOND, 0);
nov12.set(Calendar.YEAR, 2010);
nov12.set(Calendar.MONTH, 10); // November
nov12.set(Calendar.DATE, 12);

// March 12th 2011, 9:00pm (DST has ended, will begin early a.m. march
// 13th)
mar12 = Calendar.getInstance();
mar12.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
mar12.set(Calendar.HOUR_OF_DAY, 21);
mar12.set(Calendar.MINUTE, 0);
mar12.set(Calendar.SECOND, 0);
mar12.set(Calendar.YEAR, 2010);
mar12.set(Calendar.MONTH, 2); // March
mar12.set(Calendar.DATE, 12);

// March 14th 2011, 9:00pm (DST has started)
mar14 = Calendar.getInstance();
mar14.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
mar14.set(Calendar.HOUR_OF_DAY, 21);
mar14.set(Calendar.MINUTE, 0);
mar14.set(Calendar.SECOND, 0);
mar14.set(Calendar.YEAR, 2010);
mar14.set(Calendar.MONTH, 2); // March
mar14.set(Calendar.DATE, 14);
}

@Test
public void testArizonaToPacific() {
System.out.println("=== November 1st, Expected Result (0 hour) ===");
timeTestJava(nov1.getTime(), "US/Arizona", "US/Pacific");
timeTestJoda(nov1.getTime(), "US/Arizona", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== November 6th, Expected Result (0 hour) ===");
timeTestJava(nov6.getTime(), "US/Arizona", "US/Pacific");
timeTestJoda(nov6.getTime(), "US/Arizona", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== November 12th, Expected Result (-1 hour) ===");
timeTestJava(nov12.getTime(), "US/Arizona", "US/Pacific");
timeTestJoda(nov12.getTime(), "US/Arizona", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== March 12th, Expected Result (-1 hour) ===");
timeTestJava(mar12.getTime(), "US/Arizona", "US/Pacific");
timeTestJoda(mar12.getTime(), "US/Arizona", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== March 14th, Expected Result (0 hour) ===");
timeTestJava(mar14.getTime(), "US/Arizona", "US/Pacific");
timeTestJoda(mar14.getTime(), "US/Arizona", "US/Pacific");
System.out.println("=======================================\n");
}

@Test
public void testEasternToPacific() {
System.out.println("=== November 1st, Expected Result (-3 hour) ===");
timeTestJava(nov1.getTime(), "US/Eastern", "US/Pacific");
timeTestJoda(nov1.getTime(), "US/Eastern", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== November 6th, Expected Result (-3 hour) ===");
timeTestJava(nov6.getTime(), "US/Eastern", "US/Pacific");
timeTestJoda(nov6.getTime(), "US/Eastern", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== November 12th, Expected Result (-3 hour) ===");
timeTestJava(nov12.getTime(), "US/Eastern", "US/Pacific");
timeTestJoda(nov12.getTime(), "US/Eastern", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== March 12th, Expected Result (-3 hour) ===");
timeTestJava(mar12.getTime(), "US/Eastern", "US/Pacific");
timeTestJoda(mar12.getTime(), "US/Eastern", "US/Pacific");
System.out.println("=======================================\n");

System.out.println("=== March 14th, Expected Result (-3 hour) ===");
timeTestJava(mar14.getTime(), "US/Eastern", "US/Pacific");
timeTestJoda(mar14.getTime(), "US/Eastern", "US/Pacific");
System.out.println("=======================================\n");
}

// print some output from the test
private void print(Date startTime, String text, String from, String to,
Date output) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");

System.out.println(text + ":");
System.out.println("Converting " + sdf.format(startTime) + " from "
+ from + " to " + to + ".");
long difference = output.getTime() - startTime.getTime();
System.out.println("Result: " + sdf.format(output) + ". Change ("
+ difference / 1000 / 60 / 60 + " hour).\n");
}

// wrapper around joda test
private void timeTestJoda(Date startTime, String from, String to) {
Date output = convertJodaOld(startTime, TimeZone.getTimeZone(from),
TimeZone.getTimeZone(to));
print(startTime, "joda", from, to, output);
}

// wrapper around java test
private void timeTestJava(Date startTime, String from, String to) {
Date output = convertJava(startTime, TimeZone.getTimeZone(from),
TimeZone.getTimeZone(to));
print(startTime, "java", from, to, output);
}

// Joda implementation, works before and after DST change, but not during
// the period from 2am-7am UTC on the day of the change
public Date convertJodaOld(Date dt, TimeZone from, TimeZone to) {
DateTimeZone tzFrom = DateTimeZone.forTimeZone(from);
DateTimeZone tzTo = DateTimeZone.forTimeZone(to);

Date utc = new Date(tzFrom.convertLocalToUTC(dt.getTime(), false));
Date convertedTime = new Date(tzTo.convertUTCToLocal(utc.getTime()));
return convertedTime;
}

// Java implementation. Works.
public Date convertJava(Date dt, TimeZone from, TimeZone to) {
long fromOffset = from.getOffset(dt.getTime());
long toOffset = to.getOffset(dt.getTime());

long convertedTime = dt.getTime() - (fromOffset - toOffset);
return new Date(convertedTime);
}
}

谢谢!

最佳答案

不要使用“美国/亚利桑那”,它已经过时了。

使用“美国/凤凰城”

'US/Pacific' 也是如此,请改用 'America/Los_Angeles'。

关于java - 非 DST 时区的 Joda 时间转换不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5148050/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com