Java中的时间常量?


73

是否有一个Java程序包,其中包含所有烦人的时间常数,例如分钟/小时/天/年的毫秒/秒/分钟?我讨厌重复这样的事情。


3
日/年不是常数。
shmosel

2
这就是为什么他说“烦人的”时间常数的原因:-)
Brian Agnew

Answers:



128

如果您的项目中尚未包括joda-time,我将使用java TimeUnit。您不需要包括一个外部库,这很简单。

每当您需要这些“烦人的常数”时,通常都需要它们使一些数字相互交叉以进行跨单位转换。相反,您可以使用TimeUnit来简单地转换值,而无需显式乘法。

这个:

long millis = hours * MINUTES_IN_HOUR * SECONDS_IN_MINUTE * MILLIS_IN_SECOND;

变成这个:

long millis = TimeUnit.HOURS.toMillis(hours);

如果您公开了一种方法,该方法接受例如millis的某个值,然后需要对其进行转换,那么最好遵循Java并发API的作用:

public void yourFancyMethod(long somePeriod, TimeUnit unit) {
    int iNeedSeconds = unit.toSeconds(somePeriod);
}

如果您真的非常需要这些常量,则仍然可以通过调用以下命令在一个小时内获得秒数:

int secondsInHour = TimeUnit.HOURS.toSeconds(1);

3
完全同意您的解决方案,以避免不必要地依赖第三方库
M. Atif Riaz 2016年


33

Java 8 / java.time解决方案

作为的替代TimeUnit,您可能由于某些原因而更喜欢java.time包中的Duration类:

Duration.ofDays(1).getSeconds()     // returns 86400;
Duration.ofMinutes(1).getSeconds(); // 60
Duration.ofHours(1).toMinutes();    // also 60
//etc.

此外,如果您更深入地分析了Duration.ofDays(..)方法的工作原理,则会看到以下代码:

return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0);

其中SECONDS_PER_DAYLocalTime类提供的程序包保护的静态常量。

/**
 * Seconds per day.
 */
static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;

//there are also many others, like HOURS_PER_DAY, MINUTES_PER_HOUR, etc.

我认为可以肯定地说,如果有任何软件包定义了“所有令人讨厌的时间常数,如毫秒/秒/分钟”,那么您相信它们会被Java SDK开发人员使用。

为什么这个LocalTime常量包受保护而不是公开的,这是一个好问题,我相信这是有原因的。现在看来,您确实必须复制它们并自己维护。


关于为什么有人可能更喜欢Duration而不是TimeUnit的任何评论?
simpleuser

1
Duration.ofDays(1).getSeconds()TimeUnit.DAYS.toSeconds(1)仅执行计算的对象相比,它将创建并丢弃一个对象来执行其工作。
Yoory N.

1
我认为,如果您只需要将Duration转换为值,则完全没有理由使用Duration。如果需要的话,最好在API中使用Duration,在某些情况下,如果将value和unit指定为2个单独的参数,则可读性更高。我会记得有时会更新我的答案以表明这一点。
theadam '18



3

这是我用来获取毫秒数的方法。

import javax.management.timer.Timer;

Timer.ONE_HOUR
Timer.ONE_DAY
Timer.ONE_MINUTE
Timer.ONE_SECOND
Timer.ONE_WEEK

该解决方案的另一个好处是,如果您需要常量而不是方法调用(例如在批注中使用它们)时,它可以工作。
香港

3

同时TimeUnit本答案中Duration讨论和在本答案中讨论可能更直接解决的问题,也有一些其他方便的单位-的时间特征在Java中。

java.time

有关单位,请参见ChronoUnit枚举:

  • FOREVER
  • ERAS
  • MILLENNIA
  • CENTURIES
  • DECADES
  • YEARS
  • MONTHS
  • WEEKS
  • DAYS
  • HALF_DAYS
  • HOURS
  • MINUTES
  • SECONDS
  • MILLIS
  • MICROS
  • NANOS

java.time包具有复杂的枚举DayOfWeekMonth。因此,您可以传递完整的对象(例如DayOfWeek.TUESDAY或),而不是仅传递数字或字符串Month.FEBRUARY

所述java.time框架还包括类,如MonthDayYearMonthYear。同样,您可以传递完整的对象,而不仅仅是数字或字符串,以使您的代码更具自记录性,确保有效值并提供类型安全性。

TimeUnit和之间转换ChronoUnit

我们可以轻松地在TimeUnit和之间进行转换ChronoUnit。请参阅添加到旧类中的新方法TimeUnit

ThreeTen-Extra项目

ThreeTen-EXTRA项目提供额外的类与java.time工作。这些措施包括:DayOfMonthDayOfYearAmPmQuarterYearQuarterYearWeekDaysWeeksMonthsYears,和Interval


2

已经烘焙(用于多个调用)Duration实例(和0个数学运算)的另一种方法:

ChronoUnit.DAYS.getDuration().getSeconds()

0
              60 * 1000 miliseconds in 1 minute
                     60     seconds in 1 minute
                      1      minute in 1 minute
                   1/60       hours in 1 minute
              1/(60*24)        days in 1 minute
          1/(60*24*365)       years in 1 minute
1/(60*24*(365 * 4 + 1))     4 years in 1 minute
                                                * 60            is in 1 hour
                                                * 60 * 24       is in 1 day
                                                * 60 * 24 * 365 is in 1 year
                                            etc.

我想自己创建它们是最简单的。您可以使用DateCalendar类对时间和日期进行计算。使用long数据类型可处理大量数据,例如1 Januari 1970 UTC以来的毫秒数System.currentTimeMillis()


0

我对此表示怀疑,因为它们不是全部常数。一年的毫秒数不一样,对吧?


2
duffymo:当然,您是对的,但对于我们的需求,每分钟60秒就足够近似了
Yossale 2010年

0

如果您要获取值 Calendar具有与时间管理相关的所有字段,则可以进行一些简单的反映

Field []字段= Calendar.class.getFields();

for (Field f : fields)
{
  String fName = f.toString();
  System.out.println(fName.substring(fName.lastIndexOf('.')+1).replace("_", " ").toLowerCase());
}

这将输出:

era
year
month
week of year
week of month
date
day of month
day of year
day of week
day of week in month
am pm
hour
hour of day
minute
second
millisecond
zone offset
dst offset
field count
sunday
monday
tuesday
wednesday
thursday
friday
saturday
january
february
march
april
may
june
july
august
september
october
november
december
undecimber
am
pm
all styles
short
long

从中您可以排除不需要的内容。

如果只需要常量,则可以使用它们:Calendar.DAY_OF_MONTHCalendar.YEAR依此类推。


-2

如果将这些常量用作编译时常量(例如,用作批注中的属性),则将Apache DateUtils派上用场。

import org.apache.commons.lang.time.DateUtils;
DateUtils.MILLIS_PER_SECOND
DateUtils.MILLIS_PER_MINUTE
DateUtils.MILLIS_PER_HOUR
DateUtils.MILLIS_PER_DAY

这些是原始的长常量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.