任何与时间戳一起使用的高性能Java库?

时间:2011-06-24 08:37:29

标签: java performance datetime timestamp

我正在寻找高性能的Java库,它提供了允许我获取的方法:

  1. 当前时间(0-24)
  2. 当天(1-31)
  3. 本周(1-52)
  4. 当月(1-12)
  5. 当前季节(1-4)
  6. 本年度(YYYY或YY)
  7. 对我来说,性能是一个最重要的问题。这就是我不能使用标准Calendar类的原因。最好的解决方案是在不创建新对象的情况下进行所有计算。

    补充:澄清我会再提一次:每秒超过100000次操作。

9 个答案:

答案 0 :(得分:3)

你确定Calendar太慢还是只相信它?你衡量了吗?

用Java创建新对象非常便宜。保持它们是昂贵的。

也就是说,尝试Joda Time或将Java代码中的算法复制到静态辅助方法中。

答案 1 :(得分:3)

您实际上可以使用excellant joda-time库来执行此操作。 joda中的Chronology实现提供了DateTime getHour getDay类型方法背后的逻辑。如果您想跳过创建DateTime时刻,可以直接使用它。

long msSinceEpoch = System.currentTimeMillis();

Chronology chronology = ISOChronology.getInstanceUTC() // This can be static

chronology.hourOfDay().get(msSinceEpoch);
chronology.dayOfMonth().get(msSinceEpoch);
chronology.weekOfWeek().get(msSinceEpoch);
chronology.monthOfYear().get(msSinceEpoch);
chronology.years().get(msSinceEpoch);

会话不是joda的概念。根据你自己的规则,你必须从月份开始计算。

请参阅joda-time documentation on Chronology

答案 2 :(得分:2)

您可以获得当前时间并按分度和余数计算当前小时数,分钟数,秒数,毫秒数。日,月,年仅每天更换一次,因此您只需在变化时进行计算。

您可以使用缓存的日/月/年并在亚微秒时间内计算剩余时间,而无需创建对象(每天超过一次)

import java.util.Calendar;
import java.util.TimeZone;

public class Daytime {
    private static final long HOUR_MS = 3600*1000;

    public short year;
    public byte month, day;
    public byte hour, min, sec;
    public short millis;

    private long lastMillis = Integer.MIN_VALUE;
    private final TimeZone timeZone;
    private long timeOffset;

    public Daytime() {
        timeZone = TimeZone.getTimeZone("UTC");
        now();
    }

    public Daytime(TimeZone timeZone) {
        this.timeZone = timeZone;
        now();
    }

    public void now() {
        long now = System.currentTimeMillis() + timeOffset;
        if (now == lastMillis) return;
        long cachePeriod = now/HOUR_MS;
        // could the day have changed?
        if (cachePeriod != lastMillis/HOUR_MS) {
            timeOffset = timeZone.getOffset(now);
            Calendar cal = Calendar.getInstance(timeZone);
            year = (short) cal.get(Calendar.YEAR);
            month = (byte) cal.get(Calendar.MONTH);
            day = (byte) cal.get(Calendar.DAY_OF_MONTH);
            hour = (byte) cal.get(Calendar.HOUR);
        }
        millis = (short) (now % 1000);
        now /= 1000;
        sec = (byte) (now % 60);
        now /= 60;
        min = (byte) (now % 60);
    }

    public static void main(String... args) {
        Daytime dt = new Daytime();
        long start = System.nanoTime();
        final int runs = 10 * 1000 * 1000;
        for(int i=0;i< runs;i++)
            dt.now();
        long time = System.nanoTime() - start;
        System.out.printf("Daytime.now() took %.3f micro-seconds on average%n", time/1e3/runs);
    }
}

打印

Daytime.now() took 0.287 micro-seconds on average

有关夏令时变化如何发生的各种假设。您可能需要更改检查周期以满足您的需要。

答案 3 :(得分:1)

只使用一个对象并更新它的时间如下:

Date d = new Date();
...
d.setTime(System.currentTimeMillis());

答案 4 :(得分:1)

您可以使用java.util.Calander,如果不满意,可以使用Joda Time

这可以帮到你。

答案 5 :(得分:1)

您可以使用Joda Time因为它比日历快得多,并执行此操作:

LocalDateTime now = new LocalDateTime(); // automatically points to current datetime.
int hour = now.getHourOfDay();
int day = now.getDayOfMonth();
int week = now.getWeekOfWeekyear();
int month = now.getMonthOfYear();
int year = now.getYear();
int season = getSeason(day, month);

getSeason()易于实现。没有创建任何对象,没有解决方案可以做到这一切。顺便问一下,为什么你需要这么多的表现?!?!

答案 6 :(得分:1)

请注意Calendar.getInstance非常昂贵,但您通常可以通过调用该方法一次并重复使用来获取Calendar对象(除非您需要每个线程使用Calendar:Calendar不是线程安全的。)

答案 7 :(得分:1)

我已经阅读了很多关于Joda Time on SO的帖子,现在我终于下载并试了一下。

Gareth Davis的答案已被接受,我对此毫无疑问。但我很想知道Joda Time的不同之处在哪里。

基于问题和接受的答案,我创建了一个类来比较JDK Calendar和Joda Time Chronology的执行时间。

我发现Calendar实现运行速度更快,速度不是原来的两倍。

import java.util.Calendar;
import java.util.Date;

import org.joda.time.Chronology;
import org.joda.time.chrono.ISOChronology;


public class CalendarTest {

    private static final int ITERATIONS = 1000000;

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            jdkCalendar();
            jodaChronology();
        }
    }

    private static void jdkCalendar() {
        long start = System.currentTimeMillis();
        Calendar c = Calendar.getInstance();
        int hourOfDay = 0;
        int dayOfMonth = 0;
        int weekOfYear = 0;
        int month = 0;
        int year = 0;
        for (int i = 0; i < ITERATIONS; i++) {
            c.setTimeInMillis(System.currentTimeMillis());
            hourOfDay = c.get(Calendar.HOUR_OF_DAY);
            dayOfMonth = c.get(Calendar.DAY_OF_MONTH);
            weekOfYear = c.get(Calendar.WEEK_OF_YEAR);
            month = c.get(Calendar.MONTH);
            year = c.get(Calendar.YEAR);
        }
        long duration = System.currentTimeMillis() - start;
        System.err.printf("jdk:  duration %d, hourOfDay: %d, dayOfMonth: %d, weekOfYear: %d, month: %d, year: %d\n", duration, hourOfDay, dayOfMonth, weekOfYear, month, year);
    }

    private static void jodaChronology() {
        long start = System.currentTimeMillis();
        Chronology chronology = ISOChronology.getInstanceUTC(); // This can be static
        int hourOfDay = 0;
        int dayOfMonth = 0;
        int weekOfYear = 0;
        int month = 0;
        int year = 0;
        for (int i = 0; i < ITERATIONS; i++) {
            long msSinceEpoch = System.currentTimeMillis();
            hourOfDay = chronology.hourOfDay().get(msSinceEpoch);
            dayOfMonth = chronology.dayOfMonth().get(msSinceEpoch);
            weekOfYear = chronology.weekOfWeekyear().get(msSinceEpoch);
            month = chronology.monthOfYear().get(msSinceEpoch);
            year = chronology.years().getValue(msSinceEpoch);
        }
        long duration = System.currentTimeMillis() - start;
        System.err.printf("joda: duration %d, hourOfDay: %d, dayOfMonth: %d, weekOfYear: %d, month: %d, year: %d\n", duration, hourOfDay, dayOfMonth, weekOfYear, month, year);
    }

}

示例输出:

jdk:  duration 1714, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 2099, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 377, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 689, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 340, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 680, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 330, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 653, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 326, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 596, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 337, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 620, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 471, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 590, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 326, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 591, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 336, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 595, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41
jdk:  duration 327, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011
joda: duration 560, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41

答案 8 :(得分:1)

当您每次需要在调用字段的getter之前创建DateTime类的实例时,我建议使用JodaTime。但是,当您多调用getters方法而不是创建实例时,最好使用JDK 8中的java.time库或反向移植ThreeTenABP

这是因为JodaTime的DateTime类自纪元开始以来仅存储long iMillis,并且某些字段(如minutesOfHour,dayOfMonth)的所有getter始终从头开始计算该值。但是java.time的ZonedDateTime将此字段存储在单独的变量中,例如:int year, short month, short day,...
我已经创建了some benchmarks for comparision