42

I need a function that gives me how many seconds passed from the midnight. I am currently using System.currentTimeMillis() but it gives me the UNIX like timestamp.

It would be a bonus for me if I could get the milliseconds too.

Utku Zihnioglu
  • 4,714
  • 3
  • 38
  • 50

8 Answers8

82

If you're using Java >= 8, this is easily done :

ZonedDateTime nowZoned = ZonedDateTime.now();
Instant midnight = nowZoned.toLocalDate().atStartOfDay(nowZoned.getZone()).toInstant();
Duration duration = Duration.between(midnight, Instant.now());
long seconds = duration.getSeconds();

If you're using Java 7 or less, you have to get the date from midnight via Calendar, and then substract.

Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = now - c.getTimeInMillis();
long secondsPassed = passed / 1000;
Evandro
  • 137
  • 1
  • 1
  • 13
Valentin Rocher
  • 11,667
  • 45
  • 59
  • Great answer, the first one suits better for me. Thank you. – Utku Zihnioglu Dec 08 '10 at 16:14
  • If ever there were an API that needed to be immutable and assembled with Builder objects, it would be the Java SE Calendar/Date API. I can't begin to imagine what they were thinking. – scottb Oct 09 '13 at 19:42
  • That first one returns the time in *milliseconds* not seconds. But I'm sure everyone realises that :-) – Ben Clayton Oct 17 '13 at 13:45
  • You could also edit your answer to account for the fact that `DateMidnight` is deprecated now :) – avalancha Jan 30 '14 at 16:04
  • 1
    FYI, both `Calendar` and Joda-Time are now outmoded. (a) The troublesome old date-time classes such as [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html) are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. (b) The [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the java.time classes. – Basil Bourque May 02 '17 at 08:40
  • @BasilBourque added the Java8 answer to be proper – Valentin Rocher Jun 06 '17 at 12:20
  • 1
    If using Java 6 or Java 7, they should be using the [*ThreeTen-Backport*](http://www.threeten.org/threetenbp/) project to access much of the java.time functionality. Never use `Calendar`/`Date`. No need, and those legacy classes are an awful mess. – Basil Bourque Jun 06 '17 at 17:12
  • Your edits for using *java.time* are better, but (a) avoid the amorphous concept of “midnight”, (b) truncating to `DAYS` works, but seems clumsier that asking *java.time* to determine the first moment of the day with a call to `atStartOfDay` as seen in [my Answer](https://stackoverflow.com/a/34822517/642706). To be clear, days do *not* always start at 00:00:00. – Basil Bourque May 08 '18 at 21:17
  • @BasilBourque I'm using midnight because the'yre using that precise term in the question. I agree about atStartOfDay however, I'll modify it – Valentin Rocher May 09 '18 at 14:06
  • 9
    `java.time.ZonedDateTime` doesn't have the methode `atStartOfDay()` as your answer suggests. `java.time.LocalDate` has it. – frido Dec 04 '18 at 12:13
  • I'm gonna edit this answer to keep ZonedDateTime (in order to benefit from the zone info), but make it compile properly (and using some answers from @BasilBourque) – Valentin Rocher Jan 17 '20 at 15:26
  • I suggest you avoid the “midnight” terminology as it is ambiguous and confusing. If you mean first moment of the day, say so precisely with phrasing like “first moment of day” or “start of day”. – Basil Bourque Jan 17 '20 at 15:50
14

java.time

Using the java.time framework built into Java 8 and later. See Tutorial.

import java.time.LocalTime
import java.time.ZoneId

LocalTime now = LocalTime.now(ZoneId.systemDefault()) // LocalTime = 14:42:43.062
now.toSecondOfDay() // Int = 52963

It is good practice to explicit specify ZoneId, even if you want default one.

Przemek
  • 7,111
  • 3
  • 43
  • 52
  • 1
    This approach is not specific. `LocalTime` represents a time-of-day *in general*. This class knows only of generic 24-hours days. Lacking the details of a specific time zone, this class cannot know anything about anomalies such as Daylight Saving Time (DST). For example, in the United States, DST means a day can be 23, 24, or 25 hours long. So, in the US, the span of time until midnight can vary by ± 1 hour from one day to another. – Basil Bourque Jan 16 '16 at 01:06
11

tl;dr

“Midnight” is a fuzzy term, best left unsaid. Focus on the first moment of the day.

Capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone).

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

Calculate the time elapsed since the first moment of the day by calling ZonedDateTime::get and passing a ChronoField enum object.

Whole seconds.

int secondOfDay = zdt.get( ChronoField.SECOND_OF_DAY ) ;

Milliseconds.

int milliOfDay = zdt.get( ChronoField.MILLI_OF_DAY ) ;

Microseconds.

int microOfDay = zdt.get( ChronoField.MICRO_OF_DAY ) ;

Nanoseconds.

int nanoOfDay = zdt.get( ChronoField.NANO_OF_DAY ) ;

Determine first moment of the day.

Be aware that the day does not always start at 00:00:00. Some dates in some time zones may start at another time-of-day such as 01:00:00. Always let java.time determine the first moment of the day with atStartOfDay method.

Instant then =                             // Represent a moment in UTC.
    ZonedDateTime                          // Represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone).
    .now(                                  // Capture the current moment. Holds up to nanosecond resolution, but current hardware computer clocks limited to microseconds for telling current time.
        ZoneId.of( "Africa/Casablanca" )   // Specify the time zone. Never use 2-4 letter pseudo-zones such as `IST`, `PST`, `EST`.
    )                                      // Returns a `ZonedDateTime` object.
    .toLocalDate()                         // Extract the date-only portion, without time-of-day and without time zone.
    .atStartOfDay(                         // Deterimine the first moment of the day on that date in that time zone. Beware: The day does *not* always begin at 00:00:00.
        ZoneId.of( "Africa/Casablanca" )   // Specify the time zone for which we want the first moment of the day on that date.
    )                                      // Returns a `ZonedDateTime` object.
    .toInstant()                           // Adjusts from that time zone to UTC. Same moment, same point on the timeline, different wall-clock time.
;

Represent time elapsed as a Duration, a span-of-time unattached from the timeline.

Duration                                   // Represent a span-of-time unattached to the timeline in terms of hours-minutes-seconds.
.between(                                  // Specify start and stop moments.
    then ,                                 // Calculated in code seen above.
    Instant.now()                          // Capture current moment in UTC. 
)                                          // Returns a `Duration` object.
.getSeconds()                              // Extract the total number of whole seconds accross this entire span-of-time.

java.time

Java 8 and later has the java.time framework baked in.

By using ZonedDateTime and time zone, we are handling anomalies such as Daylight Saving Time (DST). For example, in the United States a day can be 23, 24, or 25 hours long. So the time until tomorrow can vary by ±1 hour from one day to another.

First get the current moment.

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

Now extract the date-only portion, a LocalDate, and use that date to ask java.time when that day began for our desired time zone. Do not assume the day began at 00:00:00. Anomalies such as Daylight Saving Time (DST) mean that the day may begin at another time such as 01:00:00.

ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( z );  // Crucial to specify our desired time zone!

Now we can get the delta between the current moment and the start of today. Such a span of time unattached to the timeline is represented by the Duration class.

Duration duration = Duration.between( todayStart , now );

Ask the Duration object for the total number of seconds in the entire span of time.

long secondsSoFarToday = duration.getSeconds();

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.

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

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

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

The simplest and fastest method to get the seconds since midnight for the current timezone:

One-time setup:

static final long utcOffset = TimeZone.getDefault().getOffset(System.currentTimeMillis());

If you use Apache Commons, you can use DateUtils.DAY_IN_MILLIS, otherwise define:

static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;

And then, whenever you need the time...:

int seconds = (int)((System.currentTimeMillis() + utcOffset) % DateUtils.DAY_IN_MILLIS / 1000);

Note that you'll need to re-setup if there's a possibility that your program will run long enough, and Daylight Saving Times change occurs...

jazzgil
  • 2,250
  • 2
  • 19
  • 20
1

Using JodaTime you can call:

int seconds = DateTime.now().secondOfDay().get();
int millis = DateTime.now().millisOfDay().get();
darrenmc
  • 1,721
  • 1
  • 19
  • 29
  • FYI, the [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [java.time](http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque May 02 '17 at 08:26
  • @BasilBourque OK, where is `millisOfDay` in `java.time` then? – izogfif Jun 04 '20 at 10:54
  • @izogfif See the top of [my Answer](https://stackoverflow.com/a/34822517/642706). `ZonedDateTime::get( ChronoField )` – Basil Bourque Jun 04 '20 at 15:40
1

Use getTime().getTime() instead of getTimeInMillis() if you get an error about calendar being protected. Remember your imports:

import java.util.*; 

will include them all while you are debugging:

    Calendar now = Calendar.getInstance();
    Calendar midnight = Calendar.getInstance();
    midnight.set(Calendar.HOUR_OF_DAY, 0);
    midnight.set(Calendar.MINUTE, 0);
    midnight.set(Calendar.SECOND, 0);
    midnight.set(Calendar.MILLISECOND, 0);
    long ms = now.getTime().getTime() - midnight.getTime().getTime();
    totalMinutesSinceMidnight = (int) (ms / 1000 / 60);
pollaris
  • 1,281
  • 17
  • 20
0
(System.currentTimeMillis()/1000) % (24 * 60 * 60)
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
secmask
  • 7,649
  • 5
  • 35
  • 52
  • 2
    This will give you the number of seconds since the beginning of the last day in UTC, not the local timezone. – robert_x44 Dec 08 '10 at 16:19
  • Of course it will work with DST transitions. The number of seconds that have elapsed since midnight do not change when a DST transition occurs; only the local time changes. – scottb Oct 09 '13 at 20:01
0

Like @secmask, if you need milli-seconds since GMT midnight, try

long millisSinceGMTMidnight = System.currentTimeMillis() % (24*60*60*1000);
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130