根据UTC(joda Interval)的不同时区处理Java夏令时

时间:2016-10-18 19:02:49

标签: java datetime jodatime

我需要根据用户提供的输入返回List<Interval> intervals。一切正常,除非范围包括夏令时。如果发生这种情况,我得到的响应在特定日期之后(在这个例子中是美国东部时间11月1日时区)有点混乱。

由于我的数据在UTC中存储为UTC,因此我使用UTC(请求是UTC,我的响应也是UTC),但是,在浏览器中,时间将转换为本地时区。在后端,我可以访问用户时区 现在的问题是如何将响应时间转换为包含夏令时的UTC时间。

public List<Interval> buildIntervals(BinInterval binSize) {
    final DateTime intervalStart = binSize.getInterval().getStart();
    final DateTime intervalEnd = binSize.getInterval().getEnd();

    final DateTimeZone tz = getCurrentUserTimezone();
    List<Interval> intervals = new ArrayList<>();

    MutableDateTime currentBinStart = new MutableDateTime(intervalStart);
    MutableDateTime currentBinEnd = new MutableDateTime(intervalStart.plus(binSize.getPeriod()));

    while (currentBinEnd.isBefore(intervalEnd)) {

    intervals.add(makeInterval(currentBinStart, currentBinEnd));

        currentBinStart = new MutableDateTime(currentBinStart.toDateTime().plus(binSize.getPeriod()));
        currentBinEnd = new MutableDateTime(currentBinEnd.toDateTime().plus(binSize.getPeriod()));

    }
} 

private static Interval makeInterval(BaseDateTime start, BaseDateTime end) {
    return new Interval(start.toDateTime().withZone(DateTimeZone.UTC),
                        end.toDateTime().withZone(DateTimeZone.UTC));
} 

以下是错误的示例回复:

第17行的正确版本应为:endDate: "2015-11-02T05:00:00.000z"

enter image description here

从第17行开始,结束时间应为+5 从第18行开始,开始时间也应该是+5,但由于某种原因,它不会在夏令时之前和之后以正确的方式转换时间。

如果我在11月1日之后选择一个范围,它可以完美地工作并将其全部转换为+5。

我当地的时区是EST。

1 个答案:

答案 0 :(得分:1)

我认为您需要为发生夏令时的特殊情况创建不同大小的间隔。

我建议您获取开始时间和结束时间的偏移量,并根据您可以决定是否需要更改结束日期的值来确定。

public static void main(String[] args) {
    DateTimeZone EDT = DateTimeZone.forID("America/Toronto");
    DateTime start = new DateTime(2016, 5, 15, 4, 0, DateTimeZone.UTC);
    DateTime end = start.plusDays(2);

    int offset1 = (int) TimeUnit.MILLISECONDS.toMinutes(EDT.getOffset(start.getMillis()));
    int offset2  = (int) TimeUnit.MILLISECONDS.toMinutes(EDT.getOffset(end.getMillis()));
    if (offset1 != offset2) {
        end = end.plusMinutes(offset1 - offset2);
    }

    System.out.println(new Interval(start.toDateTime().withZone(EDT),
            end.toDateTime().withZone(EDT)));

}