Why do Swift's Date time intervals ignore leap seconds? - swift

30 June 2012 had a leap second. As such it lasted 86401 seconds.
However, in the following Swift code, timeInterval is 86400.
How come? 🤔
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: "2012-06-30T00:00:00Z")!
let dayAfter = formatter.date(from: "2012-07-01T00:00:00Z")!
let timeInterval = date.distance(to: dayAfter)
(ps: in what context did I write this code? It was just about having fun with code. I was trying to write confusing code results, but I was disappointed by this attempt at trying to be smart)

The basis for Apple date and time APIs and system implementations is the ICU library, and the underpinnings for most of the results you see depends on ICU behavior. Notably, ICU doesn't support or consider the existence of leap seconds:
For historical reasons, the reference point is Greenwich, England. Local time in Greenwich is referred to as Greenwich Mean Time, or GMT. (This is similar, but not precisely identical, to Universal Coordinated Time, or UTC. We use the two terms interchangeably in ICU since ICU does not concern itself with either leap seconds or historical behavior.)
As such, Apple platforms also don't represent historical (or future) leap seconds in any way in APIs; systems effectively deal with leap seconds via NTP, and simply set their clocks appropriately, but querying for leap seconds like this won't yield anything.

Related

Are zero differences to UTC allowed as a timezone indicator in ISO8601

Am I right with my assumption that ISO8601 does not allow zero differences to UTC as a timezone indicator (for GMT in this case), but requires to use the Z indicator?
I want to get a second opinion on the interpretation of
The zone designator is empty if use is made of local time of the day in accordance with 5.3.1.1 through 5.3.1.3, it is the UTC designator [Z] if use is made of UTC in accordance with 5.3.3 and it is the difference-component if use is made of local time and the difference with UTC in accordance with 5.3.4.2.
because I fear one could argue that if I don't want to normalize the time but want to indicate that this is the local time used, you could still use 5.3.4.2.
So is 1985-04-12T10:15:30+00:00 a valid string according to ISO8601 or is only 1985-04-12T10:15:30Z valid?
An offset of zero, in addition to having the special representation
"Z", can also be stated numerically as "+00:00", "+0000", or "+00".
However, it is not permitted to state it numerically with a negative
sign, as "−00:00", "−0000", or "−00".
I have quoted from the Wikipedia article on ISO 8601. I cannot guarantee that the interpretation is correct, but at least it is pretty clear.
If that were me, I’d probably take the safe bet: always produce Z, but allow a positive zero difference in what I receive and parse.
After reading #Ole V.V. answer I saw that wikipedia refers to a newer version of ISO 8601. After reading a newer draft dated 2016 I found out:
4.2.5.1 Difference between local time and UTC of day
When it is required to indicate the difference between local time and UTC of day, the representation of the difference can be expressed in hours and minutes, or hours only. It shall be expressed as positive (i.e. with the leading plus sign [+]) if the local time is ahead of or equal to UTC of day and as negative (i.e. with the leading minus sign [-]) if it is behind UTC of day.
(ISO/TC 154/WG 5 N0038 ISO/WD 8601-1 2016-02-16 )
So obviously booth 1985-04-12T10:15:30+00:00 and 1985-04-12T10:15:30Z are valid but 1985-04-12T10:15:30-00:00 is not.

Why java 8 has now method in LocalDateTime class

As we aware that, in java we can use existing API's to get the current date and time, compare to that what is the difference between the new LocalDateTime class now() method.
tl;dr
If referring to Date, Calendar, and SimpleDateFormat, those are terrible old classes, now legacy. Never use.
Use only the modern java.time classes.
LocalDateTime cannot represent a moment, as it purposely lacks any concept of time zone or offset-from-UTC. So LocalDateTime.now is of no practical use.
Capture the current moment using Instant.now for UTC, or ZonedDateTime.now for a particular time zone.
Avoid legacy date-time classes
If by “existing API's” you meant the old date-time classes such as Date, Calendar, and SimpleDateFormat, you should avoid those. While they were well-intentioned industry-leading attempts at date-time handling, they proved to be poorly designed, confusing, and troublesome. They are now legacy.
Use java.time
Instead, use the java.time classes. Added to Java 8 and later. Much of the functionality was back-ported to Java 6 & 7 & Android as well.
Local… types
The “Local…” classes lack any concept of offset-from-UTC or time zone. As such, they are only a vague idea about possible moments. Without an offset or zone the have no real meaning.
An example of a local date-time is when Christmas begins, 2016-12-25T00:00:00. That does not determine a specific point on the timeline until we apply an offset or zone. Christmas starts earlier in the east. That is why Santa starts his deliveries in the Pacific such as midnight in Auckland NZ and works his way towards Asia with its later midnight, then flies the reindeer on to India after its midnight begins later, and so on westwards.
LocalDateTime not often used
So while there might be use-cases for calling now on LocalDateTime, I cannot imagine one.
The main use for LocalDateTime is in parsing strings that lack any indication of offset or zone. Such strings are poorly designed as they are incomplete. Would you communicate a price without specifying the currency? So too it is unwise to specify a date and a time but no offset/zone. At any rate, when you do have such strings lacking offset/zone, parse with LocalDateTime.
LocalDateTime ldt = LocalDateTime.parse( "2016-01-23T12:34:56.789" );
If you know the intended offset because of your given scenario, apply it.
ZoneOffset offset = ZoneOffset.ofHours( -7 );
OffsetDateTime odt = ldt.atOffset( offset ); // Now we have a moment, a specific point on the timeline.
Better yet, if you know the time zone because of your given scenario use that instead of an offset. A zone is an offset plus the set of rules for handling anomalies such as Daylight Saving Time (DST).
ZoneId zone = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zone ); // Now we have a moment, a specific point on the timeline.
In common business apps we tend to care about precise moments: When did the invoice arrive, When does the contract expire, Appointment start time, and such. For such point-on-the-timeline values, we use Instant, OffsetDateTime, and ZonedDateTime. Search Stack Overflow for many examples and more discussion. Each of these offer a now method. Calling their now method retains the important offset/zone info while capturing the current moment. In contrast, calling LocalDateTime.now discards that offset/zone info intentionally, rarely what you want.
Tip: Always pass the optional offset or zone argument to now.If omitted you are relying implicitly on the JVM’s current default time zone being applied. This default can be changed at any moment during runtime by any code on any app within that JVM. Better to specify explicitly your desired/expected offset or zone. IMHO, that optional argument should have been required to remind programmers that they must be always be consciously aware of time zone.
Current moment
Capture the current moment in UTC using Instant.
May be captured in a resolution as fine as nanoseconds but more likely microseconds or milliseconds depending on limitations of your JVM implementation, your host hardware clock, and your host OS.
Instant instant = Instant.now() ; // Capture current moment in UTC.
Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Or, as a shortcut, skip the Instant part.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
If the zone argument is omitted, the JVM’s current default time zone is applied implicitly. Better to specify your desired/expected time zone.
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.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). 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.

What datetime class should I use for my case classes?

I have case classes that may be used for representing models that originate from either a database table or API object.
Should I use joda or java.util.date or java.sql.date or?
This is for a playframework app, and I will use these models to display the datetime on the UI side of things where I will convert the date to the current users timezone also.
I'm just really confused.
Agreeing with the Answer by mkurz…
java.time
Both java.util.Date and java.sql.Date, and their related classes, have been supplanted by the java.time framework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Search Stack Overflow to learn more (after reading the Oracle Tutorial linked above). Many examples and discussions have been posted.
Basic concepts
Date-time handling is surprisingly tricky. Leave your intuition at the door.
Strings are not date-time values; they are a representation of date-time values. Focus on using objects, not strings.
You may work with a date-only, a time-only, or a date-time.
Know that offset-from-UTC is just a number of hours/minutes/seconds while a time zone is a superset, adding rules for handling anomalies such as Daylight Saving Time (DST). Use OffsetDateTime for one, and ZonedDateTime for the other.
ISO 8601 standard provides sensible formats when parsing & generating Strings to represent date-time values.
The “Local…” types mean “no specific locality”. These have no meaning, are not points on the timeline, until you specify the context of a specific time zone.
The 3-4 letter abbreviations such as EST or IST you commonly see in the media are not time zones, are not standardized, and are not unique(!). Proper time zone names are continent/region.
Apply a time zone for presentation to the user, but most of your business logic, data storage, and data exchange should be in UTC (the Instant class).
Tips
While programming, forget about your own local time zone. Think in UTC.
Learn to read & write 24-hour clock times.
I would recommend http://www.joda.org/joda-time/quickstart.html
It works really nicely with play's json formatters and comes with a ton of helpers.
You are looking for java.time.ZonedDateTime which was introduced in Java 8 and should be used for representing date and time related information that have a timezone. You can save values like 2016-05-30T00:23:27.070Z with it. There is no need to use a third party library like joda time anymore (maybe in other cases there is, but not in your's)
(Do not use java.util.Date - most of it's methods are deprecated, for good reasons)
As a blogger saied:
「Scala does not have a datetime package, but we can use the ones provided by Java.
Java 8 provides a better data/time API, so 3rd-party libraries like Joda-Time is no longer required.」
Here is the blog:
https://www.hackingnote.com/en/scala/datetime
This will be helpful to you.

How to get time interval since unix epoch reference date with precision down to the second?

We have a simple multiplayer table game that uses no networking connection. It has a pulsing animation which we want to play in sync with all other devices.
To do this I looked at NSDate -timeIntervalSinceReferenceDate to calculate a delay. Assuming all devices deliver the exact same value at the exact same time. But we found there is a difference of several seconds so this value is not very precise. Each device is a bit off from the true, correct time.
Is there an alternative, more precise way to get the time interval since reference date?
Assuming all devices deliver the exact same value at the exact same time.
That's a big (and invalid) assumption, because it's unlikely that the system time is exactly in sync on multiple devices. Asking for the current time depends on what the device thinks the current time is, and this is not guaranteed to be correct to sub-second precision.
If you wanted more precise time, you'd probably need to embed network time protocol code in your app and check with a time server. You might be better off looking into local device-to-device communication to try to sync up animations-- Bluetooth, wifi, or even something like having one device play a sound that the others can hear that would trigger the animation (e.g. a "click track", playing a repetitive sound, that other devices could sync up to).
double unixpoch = 978307200 + [[NSDate date] timeIntervalSinceReferenceDate];
...or...
double unixepoch = [[NSDate date] timeIntervalSince1970];`
Both are identical. It is very handy to take a note of that constant though, because if you start storing your times in CoreData, which uses the ref date, and want to view it in an SQLite browser, then you need to know the constant for this SQL query:
SELECT ZBATTERYRECORD.*, DATETIME(zclientcreatedat + 978307200,'unixepoch') from ZBATTERYRECORD
You may be wondering what 978307200 is for. iOS stores dates as seconds after Jan 1st, 2001 rather than 1970, so adding the 978307200 seconds will move the date forward to the epoch.

Custom DatePicker

I have two queries...
I am about to write a custom DatePicker where in could control the number of components as well. Like Date and Month only and no Year.
Q1) Do you have any custom code already available which takes care of leap year logic?
Q2) I thought of writing separate arrays of days... but writing numbers from 1 to 31 and then then repeating it for different months is annoying. Any better solution here?
Do yourself a favor and don't write your own date algorithms. NSCalendar and NSDateComponents can probably do everything you need. And using the APIs provided by the system also ensures that your code works in many different locale settings.
For example, to retrieve the number of days in a month, call [myCalendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:myDate].