How can I find the amount of seconds passed from the midnight with Java?
I need a function that gives me how many seconds passed from the midnight. I am currently using System.currentT开发者_如何学运维imeMillis()
but it gives me the UNIX like timestamp.
It would be a bonus for me if I could get the milliseconds too.
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;
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.
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?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
- See How to use ThreeTenABP….
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.
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...
Using JodaTime you can call:
int seconds = DateTime.now().secondOfDay().get();
int millis = DateTime.now().millisOfDay().get();
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);
(System.currentTimeMillis()/1000) % (24 * 60 * 60)
Like @secmask, if you need milli-seconds since GMT midnight, try
long millisSinceGMTMidnight = System.currentTimeMillis() % (24*60*60*1000);
精彩评论