joda时间DateTime.与*()的性能问题



有什么快速的方法可以创建DateTime实例并将minutes\seconds\millis设置为0吗?此时此刻,我正在使用以下代码:

private DateTime createDateTime(java.util.Date date, org.joda.time.Chronology chronology) {
    DateTime dateTime = new DateTime(date, chronology);
    dateTime = dateTime.withMinuteOfHour(0);
    dateTime = dateTime.withSecondOfMinute(0);
    dateTime = dateTime.withMillisOfSecond(0);
    return dateTime;
}

但当它调用大约200000次时,dateTime.带有***(0);需要很多时间。也许还有更正确的解决方案?

也许是这样?

// Truncate minutes/seconds/milliseconds from the date's timestamp
long truncatedTimestamp = date.getTime() - date.getTime() % 3600000;
DateTime dateTime = new DateTime(truncatedTimestamp, chronology);    

为什么速度更快?

  • 我的解决方案在DateTime构造函数中使用快速整数算术(可忽略不计)和1 unix时间戳规范化(昂贵)
  • 您的解决方案在DateTime构造函数中使用1个unix时间戳规范化(昂贵),每次将某个日期部分设置为0时使用3个以上的规范化(高昂)
  • 其他解决方案可能需要更少的代码行,但当你查看JodaTime源代码时,它们甚至需要3个以上的规范化(昂贵)

因此,你可能无法击败模。正如其他人所指出的,在非常偏远的情况下,这可能会导致不正确的结果,在这种情况下,小时不算60秒(例如,由于闰秒),尽管我不知道如何获得日历小时的开始,因为unix时间戳总是可以被截断为零(欢迎示例)。

刚刚尝试了下面的代码-它看起来就像方法1(你的)在我的电脑上花费了大约320ms,而方法2(我的)花费了390ms,方法3(Lukas's)花费了15ms,而方法4(MutableDateTime)花费了310ms。。。现在,模可能(?)导致不正确的结果。

public class Test {
    private static int NUM_RUN;
    public static void main(String[] args) {
        Date date = new Date();
        List<Runnable> list = new ArrayList<>();
        list.add(method3Withs(date));
        list.add(method1With(date));
        list.add(methodModulo(date));
        list.add(methodMutable(date));
        NUM_RUN = 100_000;
        for (Runnable r : list) {
            long start = System.nanoTime();
            r.run();
            long end = System.nanoTime();
            System.out.println((end - start) / 1000000);
        }
        NUM_RUN = 10_000_000;
        for (Runnable r : list) {
            long start = System.nanoTime();
            r.run();
            long end = System.nanoTime();
            System.out.println((end - start) / 1000000);
        }
    }
    private static Runnable method3Withs(final Date date) {
        return new Runnable() {
            @Override
            public void run() {
                DateTime d2 = null;
                for (int i = 0; i < NUM_RUN; i++) {
                    d2 = new DateTime(date);
                    d2 = d2.withMinuteOfHour(0);
                    d2 = d2.withSecondOfMinute(0);
                    d2 = d2.withMillisOfSecond(0);
                }
                System.out.println(d2);
            }
        };
    }
    private static Runnable method1With(final Date date) {
        return new Runnable() {
            @Override
            public void run() {
                DateTime d2 = null;
                for (int i = 0; i < NUM_RUN; i++) {
                    d2 = new DateTime(date);
                    d2 = d2.withTime(d2.getHourOfDay(), 0, 0, 0);
                }
                System.out.println(d2);
            }
        };
    }
    private static Runnable methodModulo(final Date date) {
        return new Runnable() {
            @Override
            public void run() {
                DateTime d2 = null;
                for (int i = 0; i < NUM_RUN; i++) {
                    long truncatedTimestamp = date.getTime() - date.getTime() % 3600000;
                    d2 = new DateTime(truncatedTimestamp);
                }
                System.out.println(d2);
            }
        };
    }
    private static Runnable methodMutable(final Date date) {
        return new Runnable() {
            @Override
            public void run() {
                MutableDateTime m = null;
                for (int i = 0; i < NUM_RUN; i++) {
                    m = new MutableDateTime(date);
                    m.setMinuteOfHour(0);
                    m.setSecondOfMinute(0);
                    m.setMillisOfSecond(0);
                }
                System.out.println(m);
            }
        };
    }
}

编辑
在10万次热身赛后,我跑了1000万次:

3037
4068
88
2864

模方法以很大的优势获胜,所以认为它在大多数情况下会表现得更好似乎是安全的。

尝试创建MutableDateTime:http://joda-time.sourceforge.net/userguide.html#Using_a_MutableDateTime,然后在其上调用toDateTime()

方法dateTime.hourOfDay().roundFloorCopy()应在单个方法调用中将minute、second和milli四舍五入为零(如果性能不是问题,则建议使用此方法)。然而,它不太可能比直接调用millis上的modulo更快。

使用类DateTimewithTime()方法怎么样,这样您只需要执行一个调用?

private DateTime createDateTime(java.util.Date date, org.joda.time.Chronology chronology) {
    DateTime dateTime = new DateTime(date, chronology);
    return dateTime.withTime(dateTime.getHourOfDay(), 0, 0, 0);
}

最新更新