joda-time DateTime.with *()的性能问题

时间:2012-04-03 11:16:38

标签: java performance jodatime

有没有快速的方法来创建DateTime实例并将minutes \ _s 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;
}

但是当它调用大约200.000次时,dateTime.with ***(0);花了很多时间。可能还有更正确的解决方案吗?

5 个答案:

答案 0 :(得分:8)

也许是这样的?

// 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
  • 时,您的解决方案在0构造函数中使用1个unix时间戳规范化(昂贵),再使用3个规范化(昂贵)
  • 其他解决方案可能需要更少的代码行,但是当您查看JodaTime源代码时,它们需要超过3个标准化(昂贵)

因此,你可能无法击败模数。 正如其他人指出的那样,这可能导致在非常偏远的角落情况下不正确的结果,其中小时不计60秒(例如由于闰秒),虽然我没有看到如何,因为unix时间戳总是可以被截断为零,以获得一个日历时间的开始(欢迎例子)。

答案 1 :(得分:5)

刚试过下面的代码 - 看起来就像方法1(你的)在我的电脑上需要大约320ms,而方法2(我的)390ms,与方法3(Lukas的)相比需要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

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

答案 2 :(得分:3)

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

答案 3 :(得分:3)

方法dateTime.hourOfDay().roundFloorCopy()应该在单个方法调用中将分钟,秒和毫秒舍入为零(如果性能不是问题,则推荐使用方法)。但是,它不可能比直接在millis上调用模数更快。

答案 4 :(得分:1)

如何使用类withTime()的{​​{1}}方法,以便您只需要拨打一个电话?

DateTime