将1周添加到日期,哪种方式首选?

时间:2010-07-21 14:29:38

标签: java datetime date calendar

我正在审查工作中的一些代码,并且遇到代码处理如何处理当前时间1周的不一致,并且想知道是否有任何理由为什么应该优先考虑另一个:

第一个是实用方法:

public static Date addDaysToDate(final Date date, int noOfDays) {
    Date newDate = new Date(date.getTime());

    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(newDate);
    calendar.add(Calendar.DATE, noOfDays);
    newDate.setTime(calendar.getTime().getTime());

    return newDate;
}

第二个使用简单的毫秒算法:

long theFuture = System.currentTimeMillis() + (86400 * 7 * 1000);
Date nextWeek = new Date(theFuture);

第二种方法显然使用“幻数”来定义一周,但这可以移动到一个常数MILLISECONDS_IN_ONE_WEEK = 86400 * 7 * 1000所以除此之外,是否有任何理由为什么这些方法中的一种应优先于另一种方法?

基本上我想要将代码更改为始终如一,但我不完全确定删除哪一个。所以任何论据都是有用的。

10 个答案:

答案 0 :(得分:22)

这两种方法在夏令时边界上的表现会有所不同。无论夏令时状态如何,第一种方法将在一天中的同一时间继续返回。第二种方法将返回在夏令时开始和结束时每个方向变化一小时的时间。

答案 1 :(得分:3)

在使用前两天caught me out的方法2时要非常小心。考虑

private static long ONE_YEAR_AS_MILLISECONDS = 365*24*60*60*1000;

这看起来很无辜,但实际上不会产生预期的,因为乘法使用整数,当乘以每个其他整数时,会导致数字溢出并产生意外结果。这是因为Java中的max int值是2,147,483,647,而一年中有31,536,000,000 ms。在我的机器上,上面的代码产生了1,471,228,928,这显然是不正确的。

相反,你需要这样做:

private static long ONE_YEAR_AS_MILLISECONDS = 365L*24L*60L*60L*1000L;

答案 2 :(得分:3)

以下内容可以在 java 8,Java 8 rocks !!

中完成
foo

答案 3 :(得分:1)

首先,我认为你用JodaTime取而代之。 http://joda-time.sourceforge.net/这是一个非常好的时间库。您需要查看此页面,了解在特定时间点添加数天或数周是多么容易:http://joda-time.sourceforge.net/key_period.html 无法执行此操作,具有不兼容JVM的移动设备。长号。

您的第一个示例更易于阅读,开发人员更容易使用。它还使用Calendar类,这是在Java中操作日期的普遍接受的方式。更好的是它有一个清晰的方法名称,可以确定它的作用。

因此,如果您重构系统以始终使用com.DaveJ.util.date.DateUtils.addDaysToDate(最终日期日期,int noOfDays),那么您可以在该方法中执行任何操作,无论是Calendar还是millis或Joda,并在您的申请中保持一致。别忘了为它写一些单元测试!

答案 4 :(得分:0)

越普遍,它就越有用。 如果你总是添加一周,我会选择第二种方法。如果您有不同的添加,我会选择第一个,如果需要,可能会将天数替换为秒或甚至毫秒。

答案 5 :(得分:0)

第一个会慢一些,所以如果性能问题,第二个会更好。

答案 6 :(得分:0)

这取决于!由于闰秒,DST和其他日历奇怪,这两者并不总是等价的。

对于商务和日常使用,总是使用第一种方法,性能也不差。它会为你处理这些事情。

对于科学需求,通常你必须使用单调时钟(这里是第二个)。

答案 7 :(得分:0)

当涉及夏令时的变化时,这两种方法可能会产生不同的结果。想象一下当前时间是23:50而在02:00时钟跳到03:00。当您只是以毫秒为单位添加7天时,第二天的时间为00:50。增加7天,结果时间仍为23:50。

为了完成混淆,您还可以尝试add(Calendar.WEEK_OF_YEAR, 1),但不确定这会有什么不同。

答案 8 :(得分:0)

由于您在移动设备上使用它,因此第一种方法更可取。原因是您的代码应该独立于特定日历,DST和其他问题,例如秒超限(闰秒)。

您必须删除对GregorianCalendar的依赖,并使用Calendar.getInstance()创建它。

答案 9 :(得分:0)

有关仅限日期的值,请参阅the Answer by javaHelperLocalDate课程故意没有时间,也没有时区。

ZonedDateTime

对于日期时间值,请使用ZonedDateTime表示日期和时间以及时区,以解决夏令时(DST)等异常情况。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime weekLater = now.plusWeeks( 1 );

或者添加一些任意天数。

ZonedDateTime later = now.plusDays( someNumberOfDays );

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了旧的麻烦日期时间类,例如java.util.Date.Calendar和& java.text.SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。

大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。