The server’s JVM’s current default time zone should be irrelevant to your programming. Always pass your desired/expected time zone in the optional arguments to various method calls. IMHO, those time zone arguments should be required rather than optional.
I do not know or use MongoDB, but this page says you the native type for a date-time value is a a 64-bit integer that represents the number of milliseconds since the Unix epoch (Jan 1, 1970) in UTC.
A date-only value is ambiguous, having no real meaning without the context of a time zone. For any given moment, the date varies around the globe by zone. A few minutes after midnight is a new day in Paris France while still “yesterday” in Montréal Canada.
So if a time zone is required, where do we get one? Ultimately, the only safe sure way is to ask the user. Prompt the user for the proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
Without asking the user, you can only assume or guess. There are ways to detect via JavaScript the web-app client browser for its current default time zone. Discussed many times already on Stack Overflow, so search. But you do not know for sure that the browser zone is intended by the user making the query to you. You could assume a time zone or assume UTC, if your users are properly trained to work that way.
Locale has nothing to do with time zone, only presentation when generating a String representation. Locale
determines (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such. You can have a Asia/Kolkata
time zone with Locale.CANADA_FRENCH
presentation, or a Pacific/Auckland
time zone with a Locale.ITALY
presentation. So, locale is irrelevant to this Question.
Use LocalDate
for the date-only portion.
LocalDate ld = LocalDate.of( 2016 , Month.MARCH , 23 );
Provide the time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
Get the start of day, the first moment. Let java.time determine this, as the first moment is not always the time-of-day 00:00:00
. Anomalies such as Daylight Saving Time (DST) may cause a different start time.
ZonedDateTime zdtStart = ld.atStartOfDay( z );
We need a ending time for the search query. Usually in date-time handling we use the Half-Open approach where the beginning is inclusive while the ending is exclusive. So we want the query for a single day to run up to, but not include, the first moment of the following day.
ZonedDateTime zdtStop = ld.plusDays( 1 ).atStartOfDay( z ); // Or, zdtStart.plusDays( 1 )
Apparently, MondoDB needs us to translate this to a count of milliseconds since the epoch in UTC. For that, extract an Instant
.
Instant instantStart = zdtStart.toInstant();
Instant instantStop = zdtStop.toInstant();
From those, extract the epoch-count. This may mean data-loss! The java.time classes tracks values with a resolution of nanoseconds. Going to milliseconds may mean truncating a fine fraction of a second.
long millisStart = instantStart.toEpochMilli(); // WARNING: possible data loss.
long millisStop = instantStop.toEpochMilli(); // WARNING: possible data loss.