如何在Java中表示5秒后?

75

我正在查看日期文档,尝试找出如何表达“现在时间 + 5秒”的方式。这是一些伪代码:

import java.util.Date
public class Main {

    public static void main(String args[]) {
         Date now = new Date();
         now.setSeconds(now.getSeconds() + 5);
    }
}

1
对于对这个问题还不熟悉的新读者,请不要使用Date。它是Java 1.0中设计不良的类,并在十年前被java.time,现代Java日期和时间API所取代。 - undefined
12个回答

101

Date 几乎完全已被弃用,但仍保留了向后兼容的原因。如果您需要设置特定日期或进行日期计算,请使用 Calendar

Calendar calendar = Calendar.getInstance(); // gets a calendar using the default time zone and locale.
calendar.add(Calendar.SECOND, 5);
System.out.println(calendar.getTime());

1
几乎全部废弃的意思是如果我的客户升级JVM,它会崩溃吗?天啊...这可能会非常糟糕。为什么他们要废除Date类? - Karl
6
很少有过时的东西会真正从JRE中删除,通常只有在功能明显有害时才会这样做。我认为在未来几个主要版本中不会删除Date,因为尽管它有一些严重的缺点,但它仍将存在并得到维护。请注意,此处的“deprecated”是指已被弃用的状态。 - Joachim Sauer
1
@Karl 我对Joachim的回答没有补充。 - Pascal Thivent
10
作为FYI,这个例子中的calendar.getTime()返回一个Date对象。我认为他们并没有过度弃用Date类,而是在弃用它的一些功能。 - Nick Stinemates
2
@Tuntable 项目Joda-Time已被JSR 310中定义的java.time类所取代,就像可怕的Date/Calendar类一样。例如:java.time.Instant.now().plusSeconds(5) - Basil Bourque
显示剩余2条评论

62

你可以使用:

now.setTime(now.getTime() + 5000);

Date.getTime()setTime()始终是指自1970年1月1日UTC 12:00:00以来的毫秒数。

Joda-Time

但是,如果您需要处理的日期/时间不仅仅是最简单的情况,我强烈建议您使用Joda Time。它是一个比Java内置支持库功能更加强大且易于使用的库。

DateTime later = DateTime.now().plusSeconds( 5 );

Java时间

Joda-Time后来启发了新的内置于Java 8中的java.time包


4
我按下F5,你的帖子不断刷新并呈现出越来越有用的信息,真是魔法。=/ - Waleed Amjad
使用日历怎么样? - Nick Stinemates
6
好吧,我不能不提Joda来回答一个java.util.Date的问题 :) - Jon Skeet
1
@Nick:日历是一个非常棘手的API,如果不正确地使用它,就无法表达“只是日期”(没有时间)或“本地日期/时间”等概念。建议使用Joda :) - Jon Skeet
嗯,对于“现在”增加5秒钟,用日期和时间来表示似乎很有用 :) - Pascal Thivent

27

来自单行代码的hacky部分:

new Date(System.currentTimeMillis() + 5000L)

从您的示例中我了解到,'now'表示'现在',而"System.currentTimeMillis()"恰好表示相同的'now'概念 :-)

但是,是的,对于比这更复杂的任何事情,Joda时间API都非常出色。


22

简而言之

Instant             // Use modern `java.time.Instant` class to represent a moment in UTC.
.now()              // Capture the current moment in UTC.
.plusSeconds( 5 )   // Add five seconds into the future. Returns another `Instant` object per the Immutable Objects pattern.

java.time

使用现代的java.time类,这些类多年前替代了可怕的DateCalendar类。

UTC

要在UTC中工作,请使用Instant

Instant later = Instant.now().plusSeconds( 5 ) ;

时区

要在特定的时区工作,请使用ZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime later = ZonedDateTime.now( z ).pluSeconds( 5 ) ;

持续时间

您可以使用Duration类来软编码添加时间的数量和粒度。

Duration d = Duration.ofSeconds( 5 ) ;
Instant later = Instant.now().plus( d ) ;  // Soft-code the amount of time to add or subtract.

关于java.time

java.time框架内置于Java 8及以上版本。这些类取代了老旧的legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle教程。在Stack Overflow上搜索许多示例和解释。规范是JSR 310

Joda-Time项目现在处于维护模式,建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。无需字符串,无需java.sql.*类。Hibernate 5和JPA 2.2支持java.time

如何获取java.time类?


10

正如其他人所指出的,在Joda中,这更容易实现:

DateTime dt = new DateTime();
DateTime added = dt.plusSeconds(5);

我强烈建议您迁移到Joda。几乎所有关于Java日期的问题都会得出Joda推荐 :-) Joda API应该是新标准Java日期API(JSR310)的基础,因此您将会朝着一个新的标准迁移。


5
"java.util.Date" 相对于 "使用 Joda Time" 就像 "Random 给我重复的值" 相对于 "不要不断创建新的 Random 实例"。 - Jon Skeet

6

忽略Dates,专注于问题。

我的偏好是使用java.util.concurrent.TimeUnit,因为它可以让我的代码更加清晰易懂。

在Java中,

long now = System.currentTimeMillis();

使用TimeUtilnow开始计算5秒后的时间是:
long nowPlus5Seconds = now + TimeUnit.SECONDS.toMillis(5);

参考资料: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html

这里提供了一个有用的链接,可以帮助你更好地理解Java中的时间单位。

3

更新:请查看使用java.time类的我的新答案。我将保留此答案作为历史记录。


Pascal Thivent的答案Jon Skeet的答案都是正确且好的。这里有一些额外的信息。

五秒钟 = PT5S(ISO 8601)

另一种表达“五秒钟之后”的方式是使用ISO 8601定义的标准格式字符串。持续时间/周期格式具有以下模式:PnYnMnDTnHnMnS,其中P标记开始,T将日期部分与时间部分分开。

因此,五秒钟为PT5S

Joda-Time

Joda-Time 2.8库可以生成和解析这种持续时间/周期字符串。请参阅PeriodDurationInterval类。您可以将Period对象加减到DateTime对象中。

在StackOverflow上搜索许多示例和讨论。这里是一个快速的示例。

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
DateTime then = now.plusSeconds( 5 );
Interval interval = new Interval( now, then );
Period period = interval.toPeriod( );

DateTime thenAgain = now.plus( period );

转储到控制台。

System.out.println( "zone: " + zone );
System.out.println( "From now: " + now + " to then: " + then );
System.out.println( "interval: " + interval );
System.out.println( "period: " + period );
System.out.println( "thenAgain: " + thenAgain );

运行时。

zone: America/Montreal
From now: 2015-06-15T19:38:21.242-04:00 to then: 2015-06-15T19:38:26.242-04:00
interval: 2015-06-15T19:38:21.242-04:00/2015-06-15T19:38:26.242-04:00
period: PT5S
thenAgain: 2015-06-15T19:38:26.242-04:00

2

我刚从Java文档中找到了这个。

import java.util.Calendar;

public class Main {

  public static void main(String[] args) {
    Calendar now = Calendar.getInstance();
    System.out.println("Current time : " + now.get(Calendar.HOUR_OF_DAY) + ":"
        + now.get(Calendar.MINUTE) + ":" + now.get(Calendar.SECOND));

    now.add(Calendar.SECOND, 100);
    System.out.println("New time after adding 100 seconds : " + now.get(Calendar.HOUR_OF_DAY) + ":"
        + now.get(Calendar.MINUTE) + ":" + now.get(Calendar.SECOND));
  }
}

我需要了解一下相关惯例吗?


哇。当Java被正确编写时,它可以变得非常冗长。你的变量名只有三个字母! - Karl

1
        String serverTimeSync = serverTimeFile.toString();
        SimpleDateFormat serverTime = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss");
        Calendar c = Calendar.getInstance();
        c.setTime(serverTime.parse(serverTimeSync));
        c.add(Calendar.MILLISECOND, 15000);
        serverTimeSync = serverTime.format(c.getTime());

你能解释一下你的代码,并讨论它所添加的价值,超越了已有的几个答案吗?Stack Overflow 的目的不仅仅是一个代码片段库。 - Basil Bourque
我在设备上有一个timeprofile.txt文件。我通过Android的BufferReader读取了它,然后添加了15秒以忘记服务器时间。 - Kalai Prakash

0

试试这个...

    Date now = new Date();
    System.out.println(now);

    Calendar c = Calendar.getInstance();
    c.setTime(now);
    c.add(Calendar.SECOND, 5);
    now = c.getTime();

    System.out.println(now);

    // Output
    Tue Jun 11 16:46:43 BDT 2019
    Tue Jun 11 16:46:48 BDT 2019

1
不要尝试这个。CalendarDate已经被几乎完全弃用。现在,回答这个问题的方法就像是 LocalDateTime result = LocalDateTime.now().plusSeconds(5); 一样简单。(其中“简单”带有通常的免责声明:“……除非你在这5秒钟内经历了某些奇怪的时区变化,等等……”) - Marco13
1
@Marco13 不要使用 LocalDateTime 来跟踪特定时刻,正如它在Javadoc中所解释的那样。对于一个瞬间,请使用 ZonedDateTimeOffsetDateTimeInstant。例如:ZonedDateTime.now( ZoneId.systemDefault() ).plusSeconds( 5 ) - Basil Bourque
1
这个答案中使用的类非常糟糕。它们如此糟糕,以至于Sun、Oracle和JCP社区在采用JSR 310定义现代java.time类时多年前就放弃了它们。在2019年建议使用这些遗留类是很差的建议。 - Basil Bourque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接