System.currentTimeMillis measuring time - java

When I use System.currentTimeMillis() to measure the time, is it safe?
E.g. When a time-shift happens (summer->winter time) will this produce an error?

No, System.currentTimeMillis() returns the number of elapsed milliseconds since the Unix epoch (midnight at the start of January 1st 1970, UTC). This does not depend on your local time zone at all.
In other words, if you call it once per second, it will always increase by about 1000 (the "about" is only due to clock accuracy and the impossibility of the calls being exactly 1 second apart). It doesn't matter if your local time zone changes its offset from UTC, or if you even change your whole time zone - that will be irrelevant.
In theory, leap seconds make all of this trickier - but in practice most applications can get away with notionally sticking their fingers in their ears and saying "I'm not at home to Mr Leap Second."

System.currentTimeMillis() will return the milliseconds since epoch (1/1/1970 00:00:00). How those are interpreted is a completely different story (and summer/winter time as well as timezone belong to the interpretation part). So yes, it would be save.

Related

java.time: the simplest way to get a difference in hours between two LocalTime objects

I want to get a difference in hours between a current time in a specific timezone and UTC time. I tried this:
LocalTime time = LocalTime.now();
System.out.println(time); //21:05:42:764
LocalTime utcTime = LocalTime.now(ZoneId.of("UTC"));
System.out.println(utcTime); //18:05:42:769
System.out.println(Duration.between(utcTime, time).getSeconds()/3600); //2
System.out.println(Duration.between(time, utcTime).getSeconds()/3600); //-3
Why is the difference between the last two results and are there better ways to do it? I need to get the number 3.
Why is the difference between the last two results
The reason that you're getting different results for the two computed durations is a combination of the fact that there is some tiny amount of time elapsed between the two recordings and the fact that the duration start time is included in the range but the duration end time is not.
Consider these times instead: 6:00:00:001 vs 8:00:00:000. Here it is very obvious that we're only exactly one millisecond off of two hours, but when we think about seconds we're either going to get 7199 or -7200. When we then do integer math (i.e. divide by 3600), we're going to get 1 or -2.
If it weren't for the one extra millisecond on the first timestamp, the absolute value of the two would be identical.
Duration is the wrong class. There is zero duration between "now" in one time zone and "now" in another. For a fun but memorable way to think about this, see here.
You appear to be seeking to know the current offset from UTC for a given time zone. You can use the ZonedDateTime class for that:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
ZoneOffset offset = zdt.getOffset();
int offsetMinutes = offset.getTotalSeconds() / 60;
double offsetHours = ((double) offsetMinutes) / 60;
System.out.println(offsetHours); // 5.5
You could also just use ZonedDateTime.now() on the first line, if you want to use the computer's current time zone.
With regard to LocalTime - that is just the time portion (hours, minutes, seconds, and smaller). Since there is no date associated, you can't necessarily determine which time zone offset it belongs to. There is more than one date that "today" going on at any given moment. Time zone offsets range from UTC-12 to UTC+14, so there are indeed values where the same time of day is happening on two different dates somewhere on the planet.
As an example, 08:00:00 in Hawaii (Pacific/Honolulu) on 2019-01-01 is also 08:00:00 in Kiribati (Pacific/Kiritimati), but on 2019-01-02 - the following date! (Reference here.) Thus, if you had a LocalTime object with 08:00:00 and it was 08:00:00 in one of those two zones, you'd not be able to tell which one it was, or what the corresponding UTC offset should be.
Also, keep in mind that time zone offsets are not limited to whole hours. There are present-day time zones with half-hour and 45-minute offset. Historically, there have been others.
Lastly, keep in mind that an offset is not necessarily enough to identify a time zone. Many time zones share offsets at some points in time, but differ in others. See "Time Zone != Offset" in the timezone tag wiki.
Oh, and about your results getting 2 in one direction and -3 in the other - this is a rounding error due to your integer division. If you print out the seconds value, you'll notice they are one second apart (10799, vs -10800). Dig closer and you'll find that "now" included fractional seconds that were truncated with the getSeconds call. (You called .now() twice, so they were at slightly different times.)

Accuracy of unix utc epoch time in seconds in java

I have seen people using System.currentTimeInMillis and converting it into seconds to store unix utc epoch time. But in Java 8 we can also use Instant.ofEpochSeconds. Which one is more accurate? Is it better to use Instant.ofEpochMillis and convert it into seconds for better accuracy ?
Well, Instant.ofEpochSecond(long) takes an argument and is used to represent an Instant. I think you meant Instant.now() which says (in part)
This will query the system UTC clock to obtain the current instant.
And, system UTC clock says (in part)
This may use System.currentTimeMillis(), or a higher resolution clock if one is available.
So the answer is, it depends. But calling System.currentTimeMillis() which (per the Javadoc) returns
the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
Note that unix epoch is in seconds.

Is TimeZone.getDSTSavings() in java returns always positive value?

Is TimeZone.getDSTSavings() in java returns always positive value or Negative values also?
I have tried this way
long millisecondsForGivenDateTime = 0l;
if (TimeZone.getTimeZone(strTZID).inDaylightTime(
new Date(millisecondsForGivenDateTime))) {
millisecondsForGivenDateTime = (millisecondsForGivenDateTime + TimeZone
.getTimeZone(strTZID).getDSTSavings());
}
here strTZID is timezone id dynamically passed to this function and millisecondsForGivenDateTime contains the dynamic value.
I am always getting 3600000 or 0 won't this function return -3600000?
In theory it could return a negative value - if you were using a TimeZone subclass where daylight saving time caused clocks to go back rather than forward.
I very much doubt you'll see that in the wild, although I have seen something similar in the Windows time zone database to get around the fact that Windows couldn't cope with time zones changing their standard UTC offset... if a zone went from UTC+5 to UTC+6 (as standard time) for example - and stopped observing DST - the zone data indicated that "DST" was actually -1 hour, and just inverted when it was in effect from what humans would expect. I've seen this with the Russian time zone, although I believe the data is cleaner now.
The desktop JRE prevents you from constructing a SimpleTimeZone with negative DST savings, but I don't know whether the same (undocumented) limitation is present in Android. You could always create your own subclass of TimeZone which did return a negative offset though.
This class returns 3600000 (1 hour) for time zones that use daylight savings time and 0 for timezones that do not, leaving it to subclasses to override this method for other daylight savings offsets.
If it were returning both positive and negative values, that would cause a two hour difference between the seasons.

Printing milliseconds of Java epoch returns 18000000?

In Joda, if I print
DateTime(GregorianChronology.getInstance())
.withYear(1970)
.withMonthOfYear(1)
.withDayOfMonth(1)
.withHourOfDay(0)
.withMinuteOfHour(0)
.withSecondOfMinute(0)
.withMillisOfSecond(0).getMillis();
I see 18000000 (this also happens to be 1/4th of MILLIS_PER_DAY, FWIW).
What I don't understand is that if the milliseconds represents the offset from the epoch which is defined as Jan-1970-01-01, then shouldn't the milliseconds be 0?
The epoch is Jan-1970-01-01 GMT. The instance you have, obviously has a different DateTimeZone. In fact it lookds like you're at GMT+5. (18000000 millis = 5 hours)
I believe the issue is related to the way Java dates include the time zone as part of there calculations.
For me, this means I'm +10 hours ahead of the epoc.
Try creating a Date/Time value that is set to 0 GMT.
The "epoch" is a specific and universal instant, a point in the universe time (like, say the moment in which the Apollo XI landed on the moon). This reference point can be represented differently in different countries (and a martian could also represent it with his own calendar). For example, for the people in England (GMT), that's the moment in which the hands of their clocks marked "00:00:00" and their (Gregorian) calendars marked "1/1/1970"; but that's just an example.
The line
DateTime(GregorianChronology.getInstance()).withYear(1970).withMonthOfYear(1)
.withDayOfMonth(1).withHourOfDay(0).withMinuteOfHour(0)
.withSecondOfMinute(0).withMillisOfSecond(0)
gives you the instant in which the clocks and the calendars in your country marked "00:00:00 1970-01-01". That's, in general, a different instant.

why does Joda Time allow a Period constructor to take two LocalTimes but there is no Duration constructor like that?

Why does Joda Time allow a Period constructor to take two LocalTimes but there is no Duration constructor like that?
I want to know because it may aid in my understanding of the best use of Joda Time.
Here's my thinking: Duration is good for social convention unaware applications and the lack of awareness is what makes it different from Period. LocalTime is good for convention unaware use because it has no timezone. This suggests Duration should be used with LocalTime and vice-versa.
A Duration is the amount of time between two precise Instants in time (which are completely independent of human concepts like years, days, and seconds). LocalTimes, however, represent ambiguous points in time (they require a date and time zone to define an Instant).
It makes sense to say there's a "standard duration" (the duration of the period assuming no DST, no leap years, no leap seconds (which Joda chronologies don't support, admittedly)) between two LocalTimes, but there's not enough information to compute a "true duration". I suspect this is why Duration doesn't have that constructor.
For example, let's suppose we have two LocalTimes: one representing 1:00 AM and 4:00 AM. 99% of the time, it'd make sense to say that's a duration of 3 hours. But, if they represent times on the day of a Daylight Saving Time switch, the duration would be 2 hours or 4 hours.
Period is defined more broadly, where it make senses to have a period between two partially-defined times like LocalTimes (just "3 hours" in the example). Periods correspond easily to standard durations, so one can just call period.toStandardDuration().

Categories