Get Time Object at Start of Day in a Particular Time Zone

Get Time Object at Start of Day in a Particular Time Zone

I ended up using the #local method on the ActiveSupport::TimeZone object passing components of the Date object.

# Get example date and time zone...
date = Date.today
timezone = ActiveSupport::TimeZone['America/New_York']

# Get beginning of day for date in timezone
timezone.local(date.year, date.month, date.day)

Rails: get #beginning_of_day in time zone

time_zone = Time.zone # any time zone really
time_zone.local(date.year, date.month, date.day)

Problem is, Date.beginning_of_day does not honor Time.zone in ActiveSupport 2.3

Compare https://github.com/rails/rails/blob/v2.3.11/activesupport/lib/active_support/core_ext/date/calculations.rb#L64 (AS 2.3)

to https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb#L74
and
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/zones.rb#L7
(AS 3)

How to get the start time and end time in utc of a day for a specified timezone in javascript?

Depending on what exactly you want to do:

// for the current day
var start = moment.tz(timezone).startOf('day').utc();
var end = moment.tz(timezone).endOf('day').utc();

// for a specific moment (m)
var start = m.clone().tz(timezone).startOf('day').utc();
var end = m.clone().tz(timezone).endOf('day').utc();

// for a specific calendar date
var m = moment.tz(date, format, timezone);
var start = m.clone().startOf('day').utc();
var end = m.clone().endOf('day').utc();

You can then format start and end however you like with the format function.

Keep in mind also that not every day starts at midnight in every time zone, nor do all local days have 24 hours.

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

Getting the startime and endtime of the day in epochmillis for different timezones - java

java.time

The modern approach uses the java.time classes only.

No need to ever use SimpleDateFormat, Date, Calendar, and the other terrible legacy date-time classes. If need be, you can convert to and fro via new conversion methods added to the old classes.

Start of day

I am trying to get the start time (00:00:00)

Do not assume the day starts at 00:00. Some dates in some zones start at another time such as 01:00. Let java.time determine the first moment of the day using LocalDate#atStartOfDay.

End of day

the end time (23:59:59) of a day

You would be missing an entire last second of the day with that approach.

Date-time work is commonly done with the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts with the first moment of the day, and runs up to, but does not include, the first moment of the following day. Half-Open approach neatly contains that full last second of the day.

Time zones

PST time zone.

There is no such thing as a time zone named PST. Such 2-4 letter pseudo-zones are used by the popular media to indicate a hint about the time zone. But these pseudo-zones are not standardized, and are not even unique! Use only for localized presentation to humans, never for data storage or data exchange.

Real time zones are named with Continent/Region.

Perhaps by “PST” you meant “Pacific Standard Time”, which often indicates America/Tijuana, or America/Los_Angeles or America/Vancouver or others.

Or perhaps by “PST” you meant “Philippines Standard Time” covering the Asia/Manila time zone.

Example code

Capture the current moment as seen in a time zone.

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

Extract the date.

LocalDate today = zdt.toLocalDate() ;

Determine the first moment of the day.

ZonedDateTime zdtStartOfDay = today.atStartOfDay( z ) ;

And determine the first moment of the following day.

ZonedDateTime zdtStartOfFollowingDay = today.plusDays( 1 ).atStartOfDay( z ) ;

You may want to see the length of time. Not all days are 24 hours.

Duration d = Duration.between( zdtStartOfDay , zdtStartOfFollowingDay ) ;

Adjust both moments to UTC by extracting an Instant object. That class represents a moment as seen in UTC.

Instant start = zdtStartOfDay.toInstant() ;
Instant end = zdtStartOfFollowingDay.toInstant() ;

For each, get the count of milliseconds since the epoch reference of first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.

long startMilli = start.toEpochMilli() ;
long endMilli = end.toEpochMilli() ;

However, I strongly recommend against tracking time as a count of milliseconds. This approach is confusing, as at least a couple dozen epoch reference points are commonly used. And a long cannot be interpreted by a human reader, so mistakes may go unnoticed.

Instead, data storage and data exchange should generally be done as text using the standard ISO 8601 formats. The java.time classes use these standard formats by default when parsing/generating text.

String startText = start.toString() ;
String endText = end.toString() ;

ThreeTen-Extra

You may want to add the ThreeTen-Extra library to your project. This gives you access to the Interval class, to represent a span of time as a pair of Instant objects.

Interval allDayLongToday = org.threeten.extra.Interval.of( start , end ) ;

This class provides several helpful methods. These include contains, encloses, abuts, union, intersection, and more.

Instant invoiceRecorded = … some `Instant` ;
boolean invoiceRecordedToday = allDayLongToday.contains( invoiceRecorded ) ;

Start of Day from one timezone to GMT

// This part you are already doing correctly.
// You get back a Moment object representing the start of the current day in Chicago:

var m = moment.tz("America/Chicago").startOf('day');

I need to get the date in epoch seconds

// Ok, so simply now get the associated Unix Time
var timestamp = m.unix();

Also note that the correct terminology is "Unix Time", not "epoch seconds".

See my blog post: "Please don't call it Epoch Time".

... but I keep getting Tue Mar 27 2018 01:00:00 GMT-0400 (EDT)

You are probably either looking at _d or a Date object, or rather the string representation of one. Don't. See this Moment.js documentation for details.

Per your comment:

I need to take the current time in a specific timezone. I then need to convert that time to the corresponding day in GMT. Finally I need to get the midnight epoch timestamp of that GMT day.

That's a little different then you originally asked, but it would be like this:

var timestamp = moment.utc().startOf('day').unix();

Note that there's no purpose in involving another time zone for this operation. Logically, when asking for "Now in time zone A converted to time zone B", it's the same as asking for "Now in time zone B". In other words, you would get the same value even when the time zone was present:

var timestamp = moment.tz('America/Chicago').utc().startOf('day').unix();

So you're better off just leaving the time zone out.

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)


Related Topics



Leave a reply



Submit