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

kal*_*n03 107 java date

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

这样的代码不准确:

 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();
}
Run Code Online (Sandbox Code Playgroud)

它毫不准确到毫秒.

RKu*_*her 156

Java 8


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());
}
Run Code Online (Sandbox Code Playgroud)

更新:我添加了这2种方法,以我的Java实用工具类在这里

它位于Maven Central Repository中:

<dependency>
  <groupId>com.github.rkumsher</groupId>
  <artifactId>utils</artifactId>
  <version>1.3</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

Java 7和早期版本


使用Apache Commons

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);
}
Run Code Online (Sandbox Code Playgroud)

没有Apache Commons

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();
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为`getStartOfDay`应该是:`LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);`即LocalTime,而不是LocalDateTime. (7认同)
  • 我建议不要采用这种方法,因为时区,夏令时等会遇到边缘情况问题,像Joda这样的时间库会为你照顾. (5认同)
  • 看起来“LocalDateTime”没有方法“atStartOfDay” (2认同)

Bas*_*que 91

半开

mprivat答案是正确的.他的观点是不要试图获得一天的结束,而是要比较"在第二天开始之前".他的想法被称为"半开放式"方法,其中一段时间​​的开始是包容性的,结尾是独占的.

  • 当前的日期时间框架是Java(java.util.Date/Calendar和Joda-Time),它们都使用了纪元的毫秒数.但在Java 8中,新的JSR 310 java.time.*类使用纳秒分辨率.如果切换到新类,基于强制一天中最后一刻的毫秒计数而编写的任何代码都将是不正确的.
  • 如果采用其他分辨率,则比较来自其他来源的数据会出错.例如,Unix库通常使用整秒,而Postgres等数据库将日期时间解析为微秒.
  • 一些夏令时变化发生在午夜,这可能会进一步混淆事情.

在此输入图像描述

Joda-Time 2.3为此目的提供了一种方法,以获得当天的第一时刻:withTimeAtStartOfDay().同样在java.time中LocalDate::atStartOfDay.

搜索StackOverflow"joda half-open"以查看更多讨论和示例.

比尔施耐德看到这篇文章,时间间隔和其他范围应该是半开放的.

避免遗留日期时间类

众所周知,java.util.Date和.Calendar类很麻烦.避免他们.

使用Joda-Time或最好使用java.time.java.time框架是非常成功的Joda-Time库的官方继承者.

java.time

java.time框架内置于Java 8及更高版本中.在ThreeTen- Backport项目中反向移植到Java 6和7,在ThreeTenABP项目中进一步适应Android .

An InstantUTC时间轴上的一个时刻,分辨率为纳秒.

Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)

应用时区来获取某个地方的挂钟时间.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Run Code Online (Sandbox Code Playgroud)

要获得当天的第一时刻,请通过LocalDate课程及其atStartOfDay方法.

ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
Run Code Online (Sandbox Code Playgroud)

使用半开放式方法,获得第二天的第一时刻.

ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
Run Code Online (Sandbox Code Playgroud)

目前,java.time框架缺少Interval如下Joda-Time所述的类.但是,ThreeTen-Extra项目使用其他类扩展了java.time.该项目是未来可能添加到java.time的试验场.其中的课程是Interval.Interval通过传递一对Instant对象来构造一个.我们可以Instant从我们的ZonedDateTime对象中提取.

Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
Run Code Online (Sandbox Code Playgroud)

乔达时间

更新:Joda-Time项目现在处于维护模式,并建议迁移到java.time类.我将这段保留完整的历史记录.

乔达时间有三个类来表示各种方式的时间跨度:Interval,Period,和Duration.An Interval具有特定的开始和结束于宇宙的时间线.这符合我们代表"一天"的需要.

我们称之为方法,withTimeAtStartOfDay而不是将时间设置为零.由于夏令时和其他异常,一天的第一时刻可能不会00:00:00.

使用Joda-Time 2.3的示例代码.

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 );
Run Code Online (Sandbox Code Playgroud)

如果必须,您可以转换为java.util.Date.

java.util.Date date = todayStart.toDate();
Run Code Online (Sandbox Code Playgroud)


mpr*_*vat 28

在getEndOfDay中,您可以添加:

calendar.set(Calendar.MILLISECOND, 999);
Run Code Online (Sandbox Code Playgroud)

虽然从数学上讲,除了说"在第二天开始之前"之外,你不能指定一天结束.

所以不if(date >= getStartOfDay(today) && date <= getEndOfDay(today))应该说,你应该说:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow)).这是一个更加可靠的定义(您不必担心毫秒精度).


Prz*_*mek 9

java.time

使用java.timeJava 8内置的框架.

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
Run Code Online (Sandbox Code Playgroud)

  • 本答案忽略了夏令时(DST)等异常情况.`Local ...`类没有时区概念和调整异常.例如,某些时区在午夜进行DST转换,因此当天的第一个时刻是在01:00:00.0(1 AM)时间而不是由00:00:00.0生成的值.这段代码.请改用"ZonedDateTime". (3认同)

lau*_*aur 6

使用 java8 java.time.ZonedDateTime 查找一天的开始而不是遍历的其他方法LocalDateTime是将输入 ZonedDateTime 截断为 DAYS:

zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS );
Run Code Online (Sandbox Code Playgroud)


Sud*_*Plz 6

#Java 8 或 ThreeTenABP

###分区日期时间

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 /sf/answers/2040212051/
Run Code Online (Sandbox Code Playgroud)

###本地日期时间

LocalDateTime curDate = LocalDateTime.now();

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

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

// based on /sf/answers/2548610851/
Run Code Online (Sandbox Code Playgroud)

我希望这对某人有帮助。