How to Obtain the Start Time and End Time of a Day

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

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.

Sample Image

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?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 brought some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android (26+) bundle implementations of the java.time classes.
    • For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
      • If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….


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

How to get the start and end times of a day

If you are only worried about .Net precision...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddTicks(-1).AddDays(1);

You really don't need to concatenate extra values onto the string for the time portion.


As an addendum, if you are using this for a query against, for example, a database...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddDays(1);

With a query of...

WHERE "startDate" >= @startDate AND "endDate" < @endDate

Then the precision issues noted in the comments won't really matter. The endDate in this case would not be part of the range, but the outside boundary.

How to get start and end of day in Javascript?

var start = new Date();
start.setUTCHours(0,0,0,0);

var end = new Date();
end.setUTCHours(23,59,59,999);

alert( start.toUTCString() + ':' + end.toUTCString() );

How to get start time and end time of a day in another timezone in Android

java.time and ThreeTenABP

I suggest using java.time, the modern Java date and time API, for such date and time math.

    ZoneId zone = ZoneId.of("America/Chicago");

String dateString = "2020-06-08";
LocalDate date = LocalDate.parse(dateString);
Instant startOfDay = date.atStartOfDay(zone).toInstant();
Instant endOfDay = date.plusDays(1).atStartOfDay(zone).toInstant();

System.out.println("The day is from " + startOfDay + " (inclusive) to " + endOfDay + " (exclusive)");

Output is:

The day is from 2020-06-08T05:00:00Z (inclusive) to
2020-06-09T05:00:00Z (exclusive)

In order not to exclude the last millisecond of the day we need to count the day as lasting up to the first moment of the next day exclusive. If you do insist on subtracting a millisecond or just a nanosecond, it’s up to you to do so, of course. For example:

    Instant endOfDay = date.plusDays(1).atStartOfDay(zone).minusNanos(1).toInstant();

The day is from 2020-06-08T05:00:00Z (inclusive) to
2020-06-09T04:59:59.999999999Z (inclusive and 1 nano more)

Edit: How to get milliseconds printed in the output? You most probably don’t need that. The format you are asking for is ISO 8601 (see the link at the bottom), the international standard. In ISO 8601 the fraction of second is optional, and leaving it out implies 0. So any API requiring ISO 8601 should accept the above. Only if not, the correct solution is to use a formatter. In this case we need to convert the time to UTC explicitly:

    ZoneId zone = ZoneId.of("America/Chicago");
DateTimeFormatter formatterWithMillis = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");

String dateString = "2020-06-08";
LocalDate date = LocalDate.parse(dateString);
OffsetDateTime startOfDay = date.atStartOfDay(zone)
.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
OffsetDateTime endOfDay = date.plusDays(1)
.atStartOfDay(zone)
.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);

String startString = startOfDay.format(formatterWithMillis);
String endString = endOfDay.format(formatterWithMillis);
System.out.println("The day is from " + startString + " (inclusive) to " + endString + " (exclusive)");

The day is from 2020-06-08T05:00:00.000Z (inclusive) to
2020-06-09T05:00:00.000Z (exclusive)

Or after subtracting a nanosecond from the end time as before:

    OffsetDateTime endOfDay = date.plusDays(1)
.atStartOfDay(zone)
.minusNanos(1)
.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);

The day is from 2020-06-08T05:00:00.000Z (inclusive) to
2020-06-09T04:59:59.999Z (inclusive and 1 nano more)

(Since the time is truncated to whole milliseconds the 1 nano more doesn’t really make sense, but I don’t think that’s the point here.)

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

But don't we have any other option apart from switching to ThreeTenBP
Library?

If you insisted, I suppose that a way through using Calendar, Date and SimpleDateFormat could be found. Those classes are poorly designed and long outdated, so with what I know and don’t know I would prefer ThreeTenABP.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
  • Wikipedia article: ISO 8601

Determine start and end time of current day (UTC - EST - UTC) ; Python

The first step of getting current time as UTC and converting it to EST seems a bit pointless. Do you use that time for anything?

Other than that it seems rather straighforward. You want to get the start and end of a day EST in UTC, so you create them and convert them to UTC. That's not so complicated. :-)

You might want to look at your matching routines though, so that you can use the start of today as the lower value, and the start of tomorrow as the higher, so you don't have to deal with that 23:59:59.9999 time.

Update:

From my original understanding of your question, this is what you want to do:

First you want to get the current date as it is in UTC (so at 11pm EST the 12st, you want the 22nd, as it is the 22nd in UTC then.

>>> from datetime import datetime
>>> today = datetime.utcnow().date()
>>> today
datetime.date(2013, 2, 21)

Secondly you want 00:00:00 of that day in UTC, as start for a search.

>>> from dateutil import tz
>>> start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc())
datetime.datetime(2013, 2, 21, 0, 0, tzinfo=tzutc())

Except that you want to know what that time is in New York:

>>> from dateutil import tz
>>> est = tz.gettz('America/New_York')
>>> start = start.astimezone(est)
>>> start
datetime.datetime(2013, 2, 20, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

And you also want tomorrow as the end:

>>> from datetime import timedelta
>>> end = start + timedelta(1)
>>> end
datetime.datetime(2013, 2, 21, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

Summary:

today = datetime.utcnow().date()
start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc()).astimezone(est)
end = start + timedelta(1)

How to obtain the end of the day when given a LocalDate?

Here are a few alternatives, depending on what you need:

LocalDate.now().atTime(23, 59, 59);     //23:59:59
LocalDate.now().atTime(LocalTime.MAX); //23:59:59.999999999

But there is no built-in method.

As commented by @JBNizet, if you want to create an interval, you can also use an interval up to midnight, exclusive.

Compare strings startTime and endTime with current time and perform action

tl;dr

LocalTime start = null ;
LocalTime end = null ;
try
{
start = LocalTime.parse( "03:19" ) ;
end = LocalTime.parse( "03:21" ) ;
}
catch ( DateTimeParseException e )
{
… handle faulty input
}

LocalTime currentTimeOfDay = LocalTime.now( ZoneId.systemDefault() ) ;
if(
( ! currentTimeOfDay.isBefore( start ) ) // "Is not before …" is a briefer way of asking "Is equal to or later than …".
&&
currentTimeOfDay.isBefore( end )
)
{ … within target times }
else
{ … outside target times }

Stop using Date & SimpleDateFormat

The Answer by Yoni is close to being the right solution, but continues your confusion by using java.util.Date class. Never use java.util.Date, just stop, let it go, move on.

Those legacy date-time classes are a wretched mess. Sun, Oracle, and the JCP community gave up on them years ago with the adoption of JSR 310. So should you.

You said:

i.e: If startTime is "13:00" and endTime is "14:00" then every day when the user uses my app at/between this time then call the function, else do nothing.

LocalTime

Represent your start and end times.

LocalTime start = LocalTime.of( 13 , 0 ) ;
LocalTime end = LocalTime.of( 14 , 0 ) ;

Capture the current moment as seen in a particular time zone.

ZoneId

You can assume the user wants to use the JVM’s default time zone.

ZoneId zoneId = ZoneId.systemDefault() ;

If critical, you should confirm with the user their intended time zone. Specify a real time zone name using format of Continent/Region, never the 2-4 letter pseudo-zones such as IST, EST, PST, etc.

ZoneId zoneId = ZoneId.of( "America/Edmonton" ) ;

ZonedDateTime

With the time zone issue decided, capture the current moment as seen in that zone.

ZonedDateTime now = ZonedDateTime.now( zoneId ) ;

Extract the time-of-day value from that moment.

LocalTime currentTimeOfDay = now.toLocalTime() ;

Compare LocalTime objects

Compare with your target start-end.

Generally best to define spans of time using the Half-Open approach, where the beginning is inclusive while the ending is exclusive.

if( 
( ! currentTimeOfDay.isBefore( start ) ) // "Is not before …" is a briefer way of asking "Is equal to or later than …".
&&
currentTimeOfDay.isBefore( end )
)
{ … within target times }
else
{ … outside target times }

Parsing

If you must obtain your start and end time-of-day values by parsing text in standard ISO 8601 format where the hour is 24-hour clock (0-23) and padding zeros are utilized, then simply call LocalTime.parse method. No need to specify a formatting pattern. No need to specify a Locale.

LocalTime start = LocalTime.parse( "03:19" ) ;
LocalTime end = LocalTime.parse( "03:21" ) ;

To protect against faulty inputs, trap for DateTimeParseException.

LocalTime start = null ;
LocalTime end = null ;
try
{
start = LocalTime.parse( "03:19" ) ;
end = LocalTime.parse( "03:21" ) ;
}
catch ( DateTimeParseException e )
{
… handle faulty input
}

How Do I Get The Events In Between Start and End Time To Display On My Calendar

I would calculate the duration (number of days), and then use that duration as the number of times to loop. Then to get the date for each day of the duration, I would use a counter variable (enumerator maybe) and add it to the date. For example when the counter is 2, then I would add 2 days to the start date to get the current date in the loop.

Hopefully this would give you an idea.

Using your example, add this to your view:

from datetime import timedelta, date

# Add this function outside the View, just like you did with the other ones
def daterange(date1, date2):
for n in range(int ((date2 - date1).days)+1):
yield date1 + timedelta(n)

def get_context_data(self, **kwargs):
## other code here ##
vacation_calendar_requests = VacationRequest.objects.filter(start_time__year = d.year,start_time__month = d.month)

# this will add a new field, "dates", to each event
for request in vacation_calendar_requests:
start_date = request.start_time
end_date = request.end_time
start_dt = date(start_date.year,start_date.month,start_date.day) # not sure if this is how you get your event start date
end_dt = date(end_date.year,end_date.month,end_date.day) # not sure if this is how you get your event end date
request.dates = [date for date in daterange(start_dt, end_dt)]

## rest of code here ##

Then in your template, add this nested loop to show the dates for each event:

{% for date in request.dates %}
{{ request.vacation_request_name }}
{{ date }} /* format the date accordingly */
{% endfor %}


Related Topics



Leave a reply



Submit