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

18

176

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

code like this is not accurate:

 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();
}

It is not accurate to the millisecond.

Drachma answered 25/4, 2012 at 1:53 Comment(7)
What do you mean it's "not accurate"?Commonalty
What's wrong with the code? What are you getting that you don't expect? What time zone do you want your days to start and end according to?Picardi
The code above does not even use the date passed into the method. It should be doing: calendar.setTime( date ) after the calendar is created.Bicuspid
This question assumes date-time values have a resolution of milliseconds. True for java.util.Date and Joda-Time. But False for java.time package in Java 8 (nanoseconds), some databases such as Postgres (microseconds), unix libraries (whole seconds), and perhaps others. See my answer for safer approach using Half-Open.Cornelia
The start of day is totally accurate to the mili. FOr the end of day why not just to TimeUnit.DAYS.toMiliseconds(1) - 1l to get the end of the day. Quite literally 'start of next day minus one' . Easy.Runesmith
Actually you should get the beginning of the next day and when iterating the items in that day (assuming you want to do that) you will specify the upper bound by using < instead of <=. That would exclude the next day but include all of the previous day down to the nanosecond.Finitude
new Date(epochMillis).toInstant().truncatedTo(ChronoUnit.DAYS).plus(1, ChronoUnit.DAYS)Falcone
C
173

tl;dr

LocalDate                       // Represents an entire day, without time-of-day and without time zone.
.now(                           // Capture the current date.
    ZoneId.of( "Asia/Tokyo" )   // Returns a `ZoneId` object.
)                               // Returns a `LocalDate` object.
.atStartOfDay(                  // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
    ZoneId.of( "Asia/Tokyo" ) 
)                               // Returns a `ZonedDateTime` object.

Start of day

Get the full length of the today as seen in a time zone.

Using Half-Open approach, where the beginning is inclusive while the ending is exclusive. This approach solves the flaw in your code that fails to account for the very last second of the day.

ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId  ) ;

ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;

zdtStart.toString() = 2020-01-30T00:00+01:00[Africa/Tunis]

zdtStop.toString() = 2020-01-31T00:00+01:00[Africa/Tunis]

See the same moments in UTC.

Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;

start.toString() = 2020-01-29T23:00:00Z

stop.toString() = 2020-01-30T23:00:00Z

If you want the entire day of a date as seen in UTC rather than in a time zone, use OffsetDateTime.

LocalDate today = LocalDate.now( ZoneOffset.UTC  ) ;

OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;

odtStart.toString() = 2020-01-30T00:00+18:00

odtStop.toString() = 2020-01-31T00:00+18:00

These OffsetDateTime objects will already be in UTC, but you can call toInstant if you need such objects which are always in UTC by definition.

Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;

start.toString() = 2020-01-29T06:00:00Z

stop.toString() = 2020-01-30T06:00:00Z

Tip: You may be interested in adding the ThreeTen-Extra library to your project to use its Interval class to represent this pair of Instant objects. This class offers useful methods for comparison such as abuts, overlaps, contains, and more.

Interval interval = Interval.of( start , stop ) ;

interval.toString() = 2020-01-29T06:00:00Z/2020-01-30T06:00:00Z

Half-Open

The answer by mprivat is correct. His point is to not try to obtain end of a day, but rather compare to "before start of next day". His idea is known as the "Half-Open" approach where a span of time has a beginning that is inclusive while the ending is exclusive.

  • The current date-time frameworks of Java (java.util.Date/Calendar and Joda-Time) both use milliseconds from the epoch. But in Java 8, the new JSR 310 java.time.* classes use nanoseconds resolution. Any code you wrote based on forcing the milliseconds count of last moment of day would be incorrect if switched to the new classes.
  • Comparing data from other sources becomes faulty if they employ other resolutions. For example, Unix libraries typically employ whole seconds, and databases such as Postgres resolve date-time to microseconds.
  • Some Daylight Saving Time changes happen over midnight which might further confuse things.

enter image description here

Joda-Time 2.3 offers a method for this very purpose, to obtain first moment of the day: withTimeAtStartOfDay(). Similarly in java.time, LocalDate::atStartOfDay.

Search StackOverflow for "joda half-open" to see more discussion and examples.

See this post, Time intervals and other ranges should be half-open, by Bill Schneider.

Avoid legacy date-time classes

The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them.

Use java.time classes. The java.time framework is the official successor of the highly successful Joda-Time library.

java.time

The java.time framework is built into Java 8 and later. Back-ported to Java 6 & 7 in the ThreeTen-Backport project, further adapted to Android in the ThreeTenABP project.

An Instant is a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.now();

Apply a time zone to get the wall-clock time for some locality.

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

To get the first moment of the day go through the LocalDate class and its atStartOfDay method.

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

Using Half-Open approach, get first moment of following day.

ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );

Table of all date-time types in Java, both modern and legacy

Currently the java.time framework lacks an Interval class as described below for Joda-Time. However, the ThreeTen-Extra project extends java.time with additional classes. This project is the proving ground for possible future additions to java.time. Among its classes is Interval. Construct an Interval by passing a pair of Instant objects. We can extract an Instant from our ZonedDateTime objects.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?


Joda-Time

UPDATE: The Joda-Time project is now in maintenance-mode, and advises migration to the java.time classes. I am leaving this section intact for history.

Joda-Time has three classes to represent a span of time in various ways: Interval, Period, and Duration. An Interval has a specific beginning and ending on the timeline of the Universe. This fits our need to represent "a day".

We call the method withTimeAtStartOfDay rather than set time of day to zeros. Because of Daylight Saving Time and other anomalies the first moment of the day may not be 00:00:00.

Example code using 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 );

If you must, you can convert to a java.util.Date.

java.util.Date date = todayStart.toDate();
Cornelia answered 12/12, 2013 at 5:54 Comment(4)
I need to use LocalDateTimeSeaddon
But what if I do need the very last nanosecond of the day using just java.time? What should I do? Use the accepted answer, the comment in the accepted answer that states that we should code .plusDays(1).atStartOfDay().minusNanos(1) or something else?Fivefinger
@PhilippeGioseffi No, you would never need to know the last minute/second/nanosecond. All that you need to know is the first moment of the following day. If you want to know if a moment occurs by the end of tomorrow: myInstant.isBefore( LocalDate.now( zoneId ).plusDays( 2 ).atStartOfDay( zoneId ).toInstant() ). Notice we added two days, to get past tomorrow, to the first moment of the day after tomorrow. I suggest you shift your thinking to the Half-Open approach. Date-time handling is much easier, and less error-prone, with Half-Open.Cornelia
@BasilBourque, I've been reading about this specific subject and got convinced that you're right. In addition to that, the user accepted the solution using with just the last second of the day.Fivefinger
G
234

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());
}

Update: I've added these 2 methods to my Java Utility Classes here

It is in the Maven Central Repository at:

<dependency>
  <groupId>com.github.rkumsher</groupId>
  <artifactId>utils</artifactId>
  <version>1.3</version>
</dependency>

Java 7 and Earlier


With 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);
}

Without 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();
}
Gait answered 1/10, 2012 at 19:9 Comment(8)
I recommend against this approach because of the edge case issues you'll run into with time zones, daylight savings, etc. that a time library like Joda will take care of for you.Putscher
I think in getStartOfDay should be: LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN); I.e. LocalTime, not LocalDateTime.Ingesta
Don't think those getEndOfDay(Date date). getStartOfDay(Date date) methods in the Java 8 section are correct, namely LocalDateTime.MAX and .MIN put you at the earliest possible dates in the past and in the future, not the beginning and ending of a day. Instead I'd suggest .atStartOfDay() for start and .plusDays(1).atStartOfDay().minusNanos(1) for end.Vine
Method localDateTimeToDate(LocalDateTime startOfDay) throws Exception - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long overflowFathom
As @KonstantinKulagin said, the answer must be corrected to LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN); Otherwise it fails with error I posted above,Fathom
@GlenMazza the Java 8 solution uses LocalTime.MAX, not LocalDateTime.MAX. The solution is correct.Piroshki
Doesn't look like LocalDateTime has method atStartOfDayPalatinate
If you are using this date for a database the without Apache commons methode won't work. The calendar.set(Calendar.MILLISECOND, 999); gets rounded, It should be: calendar.set(Calendar.MILLISECOND, 997); For database the datetime values are rounded to increments of .000, .003, or .007 seconds. #4308135Culch
C
173

tl;dr

LocalDate                       // Represents an entire day, without time-of-day and without time zone.
.now(                           // Capture the current date.
    ZoneId.of( "Asia/Tokyo" )   // Returns a `ZoneId` object.
)                               // Returns a `LocalDate` object.
.atStartOfDay(                  // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
    ZoneId.of( "Asia/Tokyo" ) 
)                               // Returns a `ZonedDateTime` object.

Start of day

Get the full length of the today as seen in a time zone.

Using Half-Open approach, where the beginning is inclusive while the ending is exclusive. This approach solves the flaw in your code that fails to account for the very last second of the day.

ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId  ) ;

ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;

zdtStart.toString() = 2020-01-30T00:00+01:00[Africa/Tunis]

zdtStop.toString() = 2020-01-31T00:00+01:00[Africa/Tunis]

See the same moments in UTC.

Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;

start.toString() = 2020-01-29T23:00:00Z

stop.toString() = 2020-01-30T23:00:00Z

If you want the entire day of a date as seen in UTC rather than in a time zone, use OffsetDateTime.

LocalDate today = LocalDate.now( ZoneOffset.UTC  ) ;

OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;

odtStart.toString() = 2020-01-30T00:00+18:00

odtStop.toString() = 2020-01-31T00:00+18:00

These OffsetDateTime objects will already be in UTC, but you can call toInstant if you need such objects which are always in UTC by definition.

Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;

start.toString() = 2020-01-29T06:00:00Z

stop.toString() = 2020-01-30T06:00:00Z

Tip: You may be interested in adding the ThreeTen-Extra library to your project to use its Interval class to represent this pair of Instant objects. This class offers useful methods for comparison such as abuts, overlaps, contains, and more.

Interval interval = Interval.of( start , stop ) ;

interval.toString() = 2020-01-29T06:00:00Z/2020-01-30T06:00:00Z

Half-Open

The answer by mprivat is correct. His point is to not try to obtain end of a day, but rather compare to "before start of next day". His idea is known as the "Half-Open" approach where a span of time has a beginning that is inclusive while the ending is exclusive.

  • The current date-time frameworks of Java (java.util.Date/Calendar and Joda-Time) both use milliseconds from the epoch. But in Java 8, the new JSR 310 java.time.* classes use nanoseconds resolution. Any code you wrote based on forcing the milliseconds count of last moment of day would be incorrect if switched to the new classes.
  • Comparing data from other sources becomes faulty if they employ other resolutions. For example, Unix libraries typically employ whole seconds, and databases such as Postgres resolve date-time to microseconds.
  • Some Daylight Saving Time changes happen over midnight which might further confuse things.

enter image description here

Joda-Time 2.3 offers a method for this very purpose, to obtain first moment of the day: withTimeAtStartOfDay(). Similarly in java.time, LocalDate::atStartOfDay.

Search StackOverflow for "joda half-open" to see more discussion and examples.

See this post, Time intervals and other ranges should be half-open, by Bill Schneider.

Avoid legacy date-time classes

The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them.

Use java.time classes. The java.time framework is the official successor of the highly successful Joda-Time library.

java.time

The java.time framework is built into Java 8 and later. Back-ported to Java 6 & 7 in the ThreeTen-Backport project, further adapted to Android in the ThreeTenABP project.

An Instant is a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.now();

Apply a time zone to get the wall-clock time for some locality.

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

To get the first moment of the day go through the LocalDate class and its atStartOfDay method.

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

Using Half-Open approach, get first moment of following day.

ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );

Table of all date-time types in Java, both modern and legacy

Currently the java.time framework lacks an Interval class as described below for Joda-Time. However, the ThreeTen-Extra project extends java.time with additional classes. This project is the proving ground for possible future additions to java.time. Among its classes is Interval. Construct an Interval by passing a pair of Instant objects. We can extract an Instant from our ZonedDateTime objects.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?


Joda-Time

UPDATE: The Joda-Time project is now in maintenance-mode, and advises migration to the java.time classes. I am leaving this section intact for history.

Joda-Time has three classes to represent a span of time in various ways: Interval, Period, and Duration. An Interval has a specific beginning and ending on the timeline of the Universe. This fits our need to represent "a day".

We call the method withTimeAtStartOfDay rather than set time of day to zeros. Because of Daylight Saving Time and other anomalies the first moment of the day may not be 00:00:00.

Example code using 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 );

If you must, you can convert to a java.util.Date.

java.util.Date date = todayStart.toDate();
Cornelia answered 12/12, 2013 at 5:54 Comment(4)
I need to use LocalDateTimeSeaddon
But what if I do need the very last nanosecond of the day using just java.time? What should I do? Use the accepted answer, the comment in the accepted answer that states that we should code .plusDays(1).atStartOfDay().minusNanos(1) or something else?Fivefinger
@PhilippeGioseffi No, you would never need to know the last minute/second/nanosecond. All that you need to know is the first moment of the following day. If you want to know if a moment occurs by the end of tomorrow: myInstant.isBefore( LocalDate.now( zoneId ).plusDays( 2 ).atStartOfDay( zoneId ).toInstant() ). Notice we added two days, to get past tomorrow, to the first moment of the day after tomorrow. I suggest you shift your thinking to the Half-Open approach. Date-time handling is much easier, and less error-prone, with Half-Open.Cornelia
@BasilBourque, I've been reading about this specific subject and got convinced that you're right. In addition to that, the user accepted the solution using with just the last second of the day.Fivefinger
H
32

in getEndOfDay, you can add:

calendar.set(Calendar.MILLISECOND, 999);

Although mathematically speaking, you can't specify the end of a day other than by saying it's "before the beginning of the next day".

So instead of saying, if(date >= getStartOfDay(today) && date <= getEndOfDay(today)), you should say: if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow)). That is a much more solid definition (and you don't have to worry about millisecond precision).

Hyson answered 25/4, 2012 at 2:5 Comment(1)
The second half of this answer is the best way. This approach is known as "Half-Open". I explain further in my answer.Cornelia
B
21

java.time

Using java.time framework built into Java 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
Backwoodsman answered 19/11, 2015 at 18:48 Comment(1)
This Answer ignores anomalies such as Daylight Saving Time (DST). The Local… classes have no concept of time zones and adjusting for anomalies. For example, some time zones have a DST change-over at midnight, so the first moment of the day is at the time 01:00:00.0 (1 AM) rather than the 00:00:00.0 value produced by this code. Use ZonedDateTime instead.Cornelia
W
6

Additional way of finding start of day with java8 java.time.ZonedDateTime instead of going through LocalDateTime is simply truncating the input ZonedDateTime to DAYS:

zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS );
Warfarin answered 2/8, 2017 at 16:45 Comment(0)
M
6

#Java 8 or ThreeTenABP

###ZonedDateTime

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://mcmap.net/q/120176/-java-8-date-time-get-start-of-day-from-zoneddatetime

###LocalDateTime

LocalDateTime curDate = LocalDateTime.now();

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

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

// based on https://mcmap.net/q/144337/-how-to-obtain-the-end-of-the-day-when-given-a-localdate

I hope that helps someone.

Micromho answered 17/5, 2018 at 20:51 Comment(4)
The "atTime" method is a very good approach togheter with the constant "LocalTime.MAX" for end of day. Nice!Selenaselenate
I can't find atStartOfDay method in LocalDateTime for java 8Indispensable
@sudoplz please describe startOfTomorrow ?Ahn
@ArnabDutta I changed the code, take a look.Micromho
S
4
private Instant getStartOfDay() {
    return Instant.now().truncatedTo(ChronoUnit.DAYS);
}

private Instant getEndOfDay() {
    return Instant.now()
            .plus(1, ChronoUnit.DAYS)
            .truncatedTo(ChronoUnit.DAYS)
            .minusNanos(1);
}
Samuella answered 7/2 at 16:34 Comment(0)
H
3

Another one solution which does not depend on any framework is:

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);
}

Note that it returns UTC based time

Heelpiece answered 31/1, 2018 at 14:31 Comment(0)
L
3

I tried this code and it works well!

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);
Linzer answered 31/7, 2018 at 6:30 Comment(1)
If you have ZonedDateTime and Instant at your disposal there is no need to ever use java.sql.Timestamp. That class is one of the terrible old legacy classes now supplanted by the java.time classes. As of JDBC 4.2, we can directly exchange java.time objects with the database. Your mixing of the legacy and modern classes makes no sense to me.Cornelia
O
2

For java 8 the following single line statements are working. In this example I use UTC timezone. Please consider to change TimeZone that you currently used.

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);

If no time difference with output. Try: ZoneOffset.ofHours(0)

Omaromara answered 14/7, 2017 at 16:23 Comment(2)
How does this add value beyond that of the existing Answers? Also, you ignore the crucial issue of time zone. And passing the UTC constant to toInstant is illegal syntax and redundant conceptually.Cornelia
@BasilBourque "How does this add value beyond that of the existing Answers?" This is how stackoverflow works. BTW this is just a template. People can change the way they want. passing UTC to toInstant is totally legal you can examine the outputs.Sams
K
2

I know it's a bit late, but in case of Java 8, if you are using OffsetDateTime (which offers a lot of advantages, such as TimeZone, Nanoseconds, etc.), you can use the following code:

OffsetDateTime reallyEndOfDay = someDay.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
// output: 2019-01-10T23:59:59.999999999Z
Kuban answered 30/8, 2019 at 19:59 Comment(0)
S
2
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.setTimeInMillis(0);
    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.setTimeInMillis(0);
    calendar.set(year, month, day, 23, 59, 59);
    return calendar.getTime();
    }

calendar.setTimeInMillis(0); gives you accuracy upto milliseconds

Shortage answered 31/1, 2020 at 9:35 Comment(5)
These terrible date-time classes were years ago supplanted by the modern java.time classes defined in JSR 310.Cornelia
@BasilBourque the package java.time only appeared in Java 8 which is available only since Android N (API 26)Juror
@Juror Most of the java.time functionality is back-ported to Java 6 & 7 in the ThreeTen-Backport library. Further adapted for early Android (<26) in the ThreeTenABP library.Cornelia
@BasilBourque but the ThreeTen uses an extremely inefficient mechanism on Android.Juror
@Juror You may be thinking of the predecessor of java.time, Joda-Time. Again, see the ThreeTenABP project. I’ve not heard of such inefficiency on Android using that library.Cornelia
C
2

Shortest answer, given your timezone being TZ:

LocalDateTime start = LocalDate.now(TZ).atStartOfDay()
LocalDateTime end = start.plusDays(1)

Compare using isAfter() and isBefore() methods, or convert it using toEpochSecond() or toInstant() methods.

Cam answered 26/2, 2021 at 17:16 Comment(0)
F
1

The following code takes the OP's original formula, and adjusts for the ms inexactness:

    private static Date getStartOfDay() {
        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);
        long approximateTimestamp = calendar.getTime().getTime();
        long extraMillis = (approximateTimestamp % 1000);
        long exactTimestamp = approximateTimestamp - extraMillis;
        return new Date(exactTimestamp);
    }

    private static Date getEndOfDay() {
        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);
        long approximateTimestamp = calendar.getTime().getTime();
        long extraMillis = (approximateTimestamp % 1000);
        long exactTimestamp = approximateTimestamp - extraMillis + 999;
        return new Date(exactTimestamp);
    }

Unlike many other answers on this thread, it is compatible with older versions of Java and Android APIs.

Fayefayette answered 30/1, 2021 at 14:55 Comment(0)
B
0

I had several inconveniences with all the solutions because I needed the type of Instant variable and the Time Zone always interfered changing everything, then combining solutions I saw that this is a good option.

        LocalDate today = LocalDate.now();
        Instant startDate = Instant.parse(today.toString()+"T00:00:00Z");
        Instant endDate = Instant.parse(today.toString()+"T23:59:59Z");

and we have as a result

        startDate = 2020-01-30T00:00:00Z
        endDate = 2020-01-30T23:59:59Z

I hope it helps you

Bac answered 30/1, 2020 at 15:41 Comment(3)
The day actually ends at the arrival of the first moment of the following day. Your code skips over the last full second of a day, a billion nanoseconds that are never reported. See my Answer to learn about Half-Open approach to defining a span-of-time.Cornelia
Manipulating strings as a way of handling date-time values is generally a poor approach. Use smart objects rather than dumb strings for this work. The java.time classes give all the functionality you need for this problem without resorting to string manipulation.Cornelia
I just now added a tl;dr section to my Answer showing how to get the range of a day as a pair of Instant objects. Tip: you may be interested in adding the ThreeTen-Extra library to your project to use its Interval class.Cornelia
G
0

I think the easiest would be something like:

// Joda Time

DateTime dateTime=new DateTime(); 

StartOfDayMillis = dateTime.withMillis(System.currentTimeMillis()).withTimeAtStartOfDay().getMillis();
EndOfDayMillis = dateTime.withMillis(StartOfDayMillis).plusDays(1).minusSeconds(1).getMillis();

These millis can be then converted into Calendar,Instant or LocalDate as per your requirement with Joda Time.

Grinder answered 26/3, 2020 at 10:47 Comment(0)
S
-2
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();
}
Swede answered 26/11, 2016 at 6:7 Comment(0)
F
-2
Date date = new Date();
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);

Timestamp:

Timestamp startTs = Timestamp.valueOf(startOfDay);
Timestamp endTs = Timestamp.valueOf(endOfDay);
Fred answered 15/9, 2021 at 11:30 Comment(1)
java.util.Date is deprecated see #5677970Nur

© 2022 - 2024 — McMap. All rights reserved.