我正在寻找高性能的Java库,它提供了允许我获取的方法:
对我来说,性能是一个最重要的问题。这就是我不能使用标准Calendar类的原因。最好的解决方案是在不创建新对象的情况下进行所有计算。
补充:澄清我会再提一次:每秒超过100000次操作。
答案 0 :(得分:3)
答案 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的概念。根据你自己的规则,你必须从月份开始计算。
答案 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