日期对象到日历[Java]


68

我有一个电影课,我有一个开始日期,一个持续时间和一个停止日期。开始和停止日期是日期对象(私有日期startDate ...)(这是一项分配,因此我无法更改),现在我想通过将持续时间(以分钟为单位)添加到startDate中来自动计算stopDate。

据我所知,不赞成使用Date的时间操纵功能,因此是不好的做法,但另一方面,我看不到将Date对象转换为日历对象以操纵时间并将其重新转换为Date对象的任何方法。有办法吗?如果有什么最佳实践


4
如果您使用大量的日期,我发现Joda Time远比Java的Date和Calendar类好:joda-time.sourceforge.net
Michael Williamson 2010年

3
分发日期/日历作业的人应受到惩罚。:-)如果我处在你的位置,我会用JAVA中加入7理智的API
SOC

Answers:


100

您可以做的是创建一个实例,GregorianCalendar然后将其设置Date为开始时间:

Date date;
Calendar myCal = new GregorianCalendar();
myCal.setTime(date);

但是,另一种方法是根本不使用Date。您可以使用如下方法:

private Calendar startTime;
private long duration;
private long startNanos;   //Nano-second precision, could be less precise
...
this.startTime = Calendar.getInstance();
this.duration = 0;
this.startNanos = System.nanoTime();

public void setEndTime() {
        this.duration = System.nanoTime() - this.startNanos;
}

public Calendar getStartTime() {
        return this.startTime;
}

public long getDuration() {
        return this.duration;
}

这样,您既可以访问开始时间,也可以获取从开始到停止的持续时间。当然,精度取决于您。


1
Java的日期/时间实现是如此糟糕,以至于我不确定更糟糕的是-保留JodaTime-即使时间计算只是我应用程序整体功能的一小部分-还是切换到Date / Calendar并花费大量时间进行半途而废一团糟,本来应该是一个实施良好的可靠组件。
Melllvar 2015年

@Melllvar如此。现在,您有了第三个选择:Java 8和更高版本中内置的java.time类。对于Java 6和7,在ThreeTen-Backport项目中已向后移植了许多java.time功能。对于早期的Android,请参见ThreeTenABP项目。至于Joda-Time,该项目现在处于维护模式,将java.time指定为其正式后继者,其创建者Stephen Colebourne领导了两个项目。
罗勒·布尔克



6

您无需为此进行转换Calendar,只需使用getTime()/即可setTime()

getTime():返回自此Date对象表示的自格林尼治标准时间1970年1月1日00:00:00以来的毫秒数。

setTime(long time):设置此Date对象以表示一个时间点,该时间点是格林尼治标准时间1970年1月1日00:00:00之后的毫秒数。)

一秒有1000毫秒,一分钟有60秒。只是做数学。

    Date now = new Date();
    Date oneMinuteInFuture = new Date(now.getTime() + 1000L * 60);
    System.out.println(now);
    System.out.println(oneMinuteInFuture);

L在后缀1000意味着这是一个long文字; 这些计算通常int很容易溢出。


2

tl; dr

Instant stop = 
    myUtilDateStart.toInstant()
                   .plus( Duration.ofMinutes( x ) ) 
;

java.time

其他答案是正确的,尤其是Borgwardt的答案。但是那些答案使用了过时的遗留类。

与Java捆绑在一起的原始日期时间类已被java.time类取代。用java.time类型执行您的业务逻辑。仅在需要使用尚未更新以处理java.time类型的旧代码的地方转换为旧类型。

如果您Calendar实际上是GregorianCalendar,则可以转换为ZonedDateTime。查找添加到旧类中的新方法,以促进与java.time类型之间的转换。

if( myUtilCalendar instanceof GregorianCalendar ) {
    GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
    ZonedDateTime zdt = gregCal.toZonedDateTime();  // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
end if 

如果您Calendar不是Gregorian,请致电toInstant以获取Instant对象。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒

Instant instant = myCal.toInstant();

同样,如果从java.util.Date对象开始,则转换为Instant。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

Instant instant = myUtilDate.toInstant();

应用时区以获取ZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

要获取java.util.Date对象,请通过Instant

java.util.Date utilDate = java.util.Date.from( zdt.toInstant() );

有关在旧式日期时间类型和java.time之间进行转换以及漂亮图表的更多讨论,请参阅对另一个问题的回答

Duration

将时间跨度表示为一个Duration对象。您输入的持续时间是问题中提到的分钟数。

Duration d = Duration.ofMinutes( yourMinutesGoHere );

您可以将其添加到起点以确定终点。

Instant stop = startInstant.plus( d ); 

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

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

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

在哪里获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置的
    • 标准Java API的一部分,具有捆绑的实现。
    • Java 9添加了一些次要功能和修复。
  • Java SE 6SE 7
    • 许多java.time功能都在ThreeTen- Backport中反向移植到Java 6和7 。
  • 安卓

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容打下了基础。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


0

就像是

movie.setStopDate(movie.getStartDate() + movie.getDurationInMinutes()* 60000);

0

这是有关如何将日期转换成不同类型的完整示例:

Date date = Calendar.getInstance().getTime();

    // Display a date in day, month, year format
    DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
    String today = formatter.format(date);
    System.out.println("Today : " + today);

    // Display date with day name in a short format
    formatter = new SimpleDateFormat("EEE, dd/MM/yyyy");
    today = formatter.format(date);
    System.out.println("Today : " + today);

    // Display date with a short day and month name
    formatter = new SimpleDateFormat("EEE, dd MMM yyyy");
    today = formatter.format(date);
    System.out.println("Today : " + today);

    // Formatting date with full day and month name and show time up to
    // milliseconds with AM/PM
    formatter = new SimpleDateFormat("EEEE, dd MMMM yyyy, hh:mm:ss.SSS a");
    today = formatter.format(date);
    System.out.println("Today : " + today);

这里使用(麻烦的日期时间类DateCalendar)现在是传统,取代年前由现代java.time类。
罗勒·布尔克
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.