关于java:如何获取一天的开始时间和结束时间?

How to obtain the start time and end time of a day?

如何获取一天的开始时间和结束时间?

这样的代码不准确:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 private Date getStartOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH);
    int day = calendar.get(Calendar.DATE);
    calendar.set(year, month, day, 0, 0, 0);
    return calendar.getTime();
}

private Date getEndOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH);
    int day = calendar.get(Calendar.DATE);
    calendar.set(year, month, day, 23, 59, 59);
    return calendar.getTime();
}

它不精确到毫秒。


Java的8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static Date atStartOfDay(Date date) {
    LocalDateTime localDateTime = dateToLocalDateTime(date);
    LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
    return localDateTimeToDate(startOfDay);
}

public static Date atEndOfDay(Date date) {
    LocalDateTime localDateTime = dateToLocalDateTime(date);
    LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
    return localDateTimeToDate(endOfDay);
}

private static LocalDateTime dateToLocalDateTime(Date date) {
    return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}

private static Date localDateTimeToDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

更新:我已经添加到我的utility 2这些方法的Java类。 P / < >

  • dateutils.atstartofday
  • dateutils.atendofday

它也在Maven中央repository美元: P / < >

1
2
3
4
5
<dependency>
  <groupId>com.github.rkumsher</groupId>
  utils</artifactId>
  <version>1.3</version>
</dependency>

Java和earlier 7 与Apache下议院

1
2
3
4
5
6
7
public static Date atEndOfDay(Date date) {
    return DateUtils.addMilliseconds(DateUtils.ceiling(date, Calendar.DATE), -1);
}

public static Date atStartOfDay(Date date) {
    return DateUtils.truncate(date, Calendar.DATE);
}

没有Apache下议院

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Date atEndOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    calendar.set(Calendar.MILLISECOND, 999);
    return calendar.getTime();
}

public Date atStartOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar.getTime();
}


半开放

"mprivat by答案也是的先生。他一点也不去试着获得一天的结束",但比较到"的开始,而在第二天的"。他的主意也被称为"半开放"的方法在学校的时间的开始,而费用支付的结局是专有的。 P / < >

  • "当前的日期-时间也frameworks Java(java.util.date /日历和尤达大师的时间)都使用milliseconds从时代。但在Java 8,纽约jsr 310 java.time。*类使用nanoseconds决议。你写的任何代码的基础上forcing的milliseconds count of最后时刻的一天会incorrect如果switched *的新类。
  • comparing数据从其他来源变得faulty如果他们运用其他resolutions。例如,UNIX libraries typically运用整个秒,和这样一个databases postgres解决日期-时间到microseconds。
  • 一些白天的时间发生在午夜节能的变化,可能会进一步confuse的事情。

enter image description here P / < >

尤达大师- 2.3时代提供的方法为这一专用,到获得第一矩的一天:withTimeAtStartOfDay()。similarly在java.time,LocalDate::atStartOfDay。 P / < >

搜索stackoverflow为"尤达大师半开放"看到更多的discussion和examples。 P / < >

看到这个帖子的时候,intervals和其他ranges应该半开放,由比尔施耐德。 P / < > 避免传统的日期时间类

"java.util.date和日历。类是notoriously troublesome。避免他们。 P / < >

无论是使用时间或尤达大师,preferably,java.time。"java.time框架的官方successor *高度成功的尤达大师的时间的图书馆。 P / < > java.time

"java.time框架也建成Java 8和以后。背ported到Java 6 & AMP;7在threeten - backport项目,进一步adapted到Android在threetenabp项目。 P / < >

一个Instant的刻上timeline在UTC与nanoseconds的决议。 P / < >

1
Instant instant = Instant.now();

apply的时间区得到华尔-时钟的时间为一些locality。 P / < >

1
2
ZoneId zoneId = ZoneId.of("America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

得到的第一矩的一天去通过LocalDate类和它的atStartOfDay法。 P / < >

1
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );

用半开放的方法,得到以下的第一刻的一天。 P / < >

1
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );

目前的java.time框架缺乏一Interval舱航班被描述为以下,尤达大师的时间的。然而,threeten额外的项目extends java.time与额外的类。这个项目的proving归为可能的未来additions到java.time。among其类也Interval。构建一个Intervalby经过的对银行Instant的物体。我们可以从我们的一个Instant提取物ZonedDateTime的物体。 P / < >

1
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );

尤达大师的时间

更新:尤达大师的时间的项目,现在在我们维修模式,和advises迁移到java.time类。我离开这段intact为历史。 P / < >

尤达大师-时间三类到represent男孩回来了很多的时间在各种方式:IntervalPeriod,和Duration。一个Interval腹部的特定的开始和结束的timeline之宇宙。这fits我们需要represent"一天"。 P / < >

我们知道withTimeAtStartOfDay方法而不是设定时间的一天到zeros。因为白天的时间上和其他异常的第一矩的一天可能不是00:00:00。 P / < >

例子代码使用Joda时间2.3。 P / < >

1
2
3
4
5
DateTimeZone timeZone = DateTimeZone.forID("America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTime todayStart = now.withTimeAtStartOfDay();
DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay();
Interval today = new Interval( todayStart, tomorrowStart );

如果你要,你可以convert到java.util.date。 P / < >

1
java.util.Date date = todayStart.toDate();


在getendofday,你可以给我: P / < >

1
calendar.set(Calendar.MILLISECOND, 999);

虽然mathematically speaklng,你找不specify"结束"的一天超过by说"前开始的第二天。" P / < >

所以代替说,if(date >= getStartOfDay(today) && date <= getEndOfDay(today)),你应该说:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))。那是在多更多的固体的定义(和你不用担心millisecond精密)。 P / < >


java.time

java.time框架建到Java的8。 P / < >

1
2
3
4
5
6
7
8
9
import java.time.LocalTime;
import java.time.LocalDateTime;

LocalDateTime now = LocalDateTime.now(); // 2015-11-19T19:42:19.224
// start of a day
now.with(LocalTime.MIN); // 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); // 2015-11-19T00:00
// end of a day
now.with(LocalTime.MAX); // 2015-11-19T23:59:59.999999999


使用java8 java.time.zonedDateTime而不是通过LocalDateTime查找开始日期的其他方法是简单地将输入zonedDateTime截断为天:

1
zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS );


Java 8或三重表分区日期时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ZonedDateTime curDate = ZonedDateTime.now();

public ZonedDateTime startOfDay() {
    return curDate
    .toLocalDate()
    .atStartOfDay()
    .atZone(curDate.getZone())
    .withEarlierOffsetAtOverlap();
}

public ZonedDateTime endOfDay() {

    ZonedDateTime startOfTomorrow =
        curDate
        .toLocalDate()
        .plusDays(1)
        .atStartOfDay()
        .atZone(curDate.getZone())
        .withEarlierOffsetAtOverlap();

    return startOfTomorrow.minusSeconds(1);
}

// based on https://stackoverflow.com/a/29145886/1658268

。本地日期时间

1
2
3
4
5
6
7
8
9
10
11
LocalDateTime curDate = LocalDateTime.now();

public LocalDateTime startOfDay() {
    return curDate.atStartOfDay();
}

public LocalDateTime endOfDay() {
    return startOfTomorrow.atTime(LocalTime.MAX);  //23:59:59.999999999;
}

// based on https://stackoverflow.com/a/36408726/1658268

我希望这能帮助别人。


对于Java 8,下面的单行语句正在工作。在这个例子中,我使用的是UTC时区。请考虑更改当前使用的时区。

1
2
3
4
5
6
7
8
9
10
11
System.out.println(new Date());

final LocalDateTime endOfDay       = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
final Date          endOfDayAsDate = Date.from(endOfDay.toInstant(ZoneOffset.UTC));

System.out.println(endOfDayAsDate);

final LocalDateTime startOfDay       = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
final Date          startOfDayAsDate = Date.from(startOfDay.toInstant(ZoneOffset.UTC));

System.out.println(startOfDayAsDate);

如果输出没有时间差。试一试:ZoneOffset.ofHours(0)


我试过这个代码,它运行得很好!

1
2
3
4
5
final ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
final ZonedDateTime startofDay =
    now.toLocalDate().atStartOfDay(ZoneOffset.UTC);
final ZonedDateTime endOfDay =
    now.toLocalDate().atTime(LocalTime.MAX).atZone(ZoneOffset.UTC);


另一个不依赖任何框架的解决方案是:

1
2
3
4
5
6
7
8
9
static public Date getStartOfADay(Date day) {
    final long oneDayInMillis = 24 * 60 * 60 * 1000;
    return new Date(day.getTime() / oneDayInMillis * oneDayInMillis);
}

static public Date getEndOfADay(Date day) {
    final long oneDayInMillis = 24 * 60 * 60 * 1000;
    return new Date((day.getTime() / oneDayInMillis + 1) * oneDayInMillis - 1);
}

请注意,它返回基于UTC的时间


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static Date beginOfDay(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    return cal.getTime();
}

public static Date endOfDay(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.HOUR_OF_DAY, 23);
    cal.set(Calendar.MINUTE, 59);
    cal.set(Calendar.SECOND, 59);
    cal.set(Calendar.MILLISECOND, 999);

    return cal.getTime();
}

我试过了这个代码,和它的工作好。: P / < >

1
2
3
4
5
6
7
8
9
10
11
12
Date d= new Date();
GregorianCalendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
String s_d=d.getYear()+"-"+(d.getMonth()+1)+"-"+d.getDay();
DateFormat dateFormat = DateFormat.getDateInstance();
try {
// for the end of day :
c.setTime(dateFormat.parse(s_d+" 23:59:59"));
// for the start of day:
//c.setTime(dateFormat .parse(s_d+" 00:00:00"));
} catch (ParseException e) {
e.printStackTrace();
}