I'm trying to retrieve the Unix timestamp for midnight of the current day. Timezone not relevant. I'm looking for something like: 1625716800 Every tutorial I've found is for retrieving formatted strings, such as: "Thu Jul 08 2021 04:00:00" It needs to be midnight. Not just the current seconds or milliseconds. Any advice is appreciated. Many thanks.
-
2@MarsAtomic "arithmetic skills" strongly suggests you feel the answer involves arithmetic. This is quite incorrect. The correct answer involves the java.time package and zero arithmetic. – rzwitserloot Jul 08 '21 at 01:56
-
I'm half-way there I think. I just need to convert this to the Unix epoch. Calendar cal = Calendar.getInstance(); cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0); System.out.println(cal.getTime()); – solitario Jul 08 '21 at 02:35
-
1Time zone is not only relevant, it’s crucial. Midnight falls at different times in different time zones. – Ole V.V. Jul 08 '21 at 05:34
-
1I recommend you don’t use `Calendar`. That class is poorly designed and long outdated. Instead use classes from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jul 08 '21 at 05:35
2 Answers
I'm trying to retrieve the Unix timestamp for midnight of the current day. Timezone not relevant.
This is impossible. The concept of 'a day' does not exist in unix timestamp space. This space just ticks away 1 unit every millisecond that passes, since some universally defined epoch (in unix space, that epoch occurred at that instant in time when someone in greenwich, UK, would tell you that right this very moment it is jan 1st, 1970, midnight). There's no such thing as days in this system, no such thing as dates. Just 'millis since the epoch', and that's all you get.
If you want concepts like 'day', 'month', or 'hour', you simply can't do that in this space; these are human concepts and you can't know what the right answer is unless you involve a political unit which decides how to translate such an epoch to an actual 'it is this date in this month in this year, this hour, this minute, etc'. Political units have timezones, daylight savings times, and more - and they all effect when 'midnight' might be.
When it is midnight in Europe/Amsterdam, it's not midnight in Asia/Singapore. Hopefully this helps you understand that the concept 'at midnight' doesn't make sense unless you add to this some notion of 'where'. Could be 'whereever the system thinks it is', (e.g. platform default timezone), could be at the essentially fictional UTC timezone, could be at some specific timezone, could be at a user-specified timezone. But it's gotta be in some timezone.
Furthermore, 'current day' is ambiguous. That, too, just isn't a thing unless timezones are involved. Current day where? Amsterdam? Singapore? Los Angeles? As I said, millis-since-epoch has no idea what 'day' means. It just knows when the epoch was and what a millisecond is, and it knows nothing more.
In fact, 'midnight' doesn't work at all. It may not exist. Most places will advance the clock by an hour, if they do so at all, at 2 AM, but not all zones do. Thus, midnight may simply be a time that never was. One moment in time it is 23:59:59 on March 22nd. The next moment in time, it is 01:00:00 on March 23rd. Presumably what you actually mean is 'start of day', as in, the very first instant in time that can be called 'the date is now X' in the decided time zone. Which usually is 00:00:00 but there are extremely exotic cases where it's not. The problem is, 'extremely exotic' is not equal to 'never happens'.
Let's assume the zone relevant for 'current day' and 'at the start of this day' are all from the same zone, then what you're looking for:
ZoneId zone = ....;
ZonedDateTime zdt = ZonedDateTime.now(zone);
zdt = zdt.toLocalDate().atStartOfDay(zone);
long v = zdt.toInstant().toEpochMilli();
Where zone can be many things. For example, ZoneOffset.UTC
, or ZoneId.systemDefault()
, or ZoneId.of("Europe/Amsterdam")
for example.
Let's give it a whirl with ZoneOffset.UTC
:
ZoneId zone = ZoneOffset.UTC;
ZonedDateTime zdt = ZonedDateTime.now(zone);
zdt = zdt.toLocalDate().atStartOfDay(zone);
long v = zdt.toInstant().toEpochMilli();
System.out.println(v);
See this code run live at IdeOne.com:
1625702400000

- 303,325
- 100
- 852
- 1,154

- 85,357
- 5
- 51
- 72
-
-
I’ll restrain myself, but I have an urge to prepend a *tl;dr* section up top that says simply: `LocalDate.now( ZoneId.of( "Europe/Madrid" ) ).atStartOfDay( ZoneId.of( "Europe/Madrid" ) ).toInstant().toEpochMilli()` – Basil Bourque Jul 08 '21 at 05:53
-
@BasilBourque depositing a pre-chewed answer without explaining why that is the right answer leads to people thinking that `strtotime('today')` is sensible code. Then again, my attempt to explain the 'why' clearly didn't stick in this case, so perhaps your approach would have been better. – rzwitserloot Jul 08 '21 at 13:43
-
I too tend to think that *This is impossible.* is the better introduction to the answer in this particular case. It’s a pretty important message. Also @BasilBourque – Ole V.V. Jul 08 '21 at 19:02
import java.util.Calendar;
class test{
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0);
System.out.println(cal.getTimeInMillis());
}
}

- 15
- 1
- 3
-
2Calendar is an obsolete API. This code also has silent important assumptions, which is a bad idea (this code uses 'platform local timezone', which is a different way of saying 'will fail in an untestable way'). Do not use this code. – rzwitserloot Jul 08 '21 at 03:14