17
$\begingroup$

Bug introduced in V10.4 or earlier and persisting through 12.1.1

(CASE:3920785)


Back in version 10.2 or so, Mathematica began supporting the ISO 8601 date/time format, which is nice because it's used pretty frequently. You can target the format with DateString:

DateString["ISODateTime"]
(* "2017-04-28T11:45:14" *)

which was the current time when I typed that. You can import from a string using DateObject, like so:

DateObject["2017-04-28T11:45:14"]
(* DateObject[{2017, 4, 28, 11, 45, 14}, "Instant", "Gregorian", -4.] *)

The last element there is the time zone, which defaults to $SystemTimeZone, will be important later. It looks prettier in StandardForm. However, I had an externally generated string:

isoDateString = "2017-04-28T01:50:52.000Z";

If you look at the doubtless highly authoritative Wikipedia article, you'll see that the "Z" at the end there means that it should be UTC time, or in Mathematica parlance, it should have 0 for its time zone. Sadly, no!

DateObject[isoDateString]
(* DateObject[{2017, 4, 28, 1, 50, 52.}, "Instant", "Gregorian", -4.] *)

It's still using the default time zone! Is there any way to correct this that doesn't require manual string munging?

$\endgroup$
  • 4
    $\begingroup$ For the sake of an update, even 12.0+ this seems to persist. I have a bunch of data in the form "2019-11-17T00:00:00-05:00" with the 'explicit' timezone offset format, still can't be interpreted as a date. $\endgroup$ – flip Nov 20 '19 at 3:28
9
$\begingroup$

Just got hit by this 'issue', don't feel competent enough but it looks like something that should be reported.

So in case you know you will get UTC time (like it is in my case, this is very common setting for server responses etc) you can do:

isoDateString = "2017-04-28T01:50:52.000Z";

TimeZoneConvert @ DateObject[ isoDateString, TimeZone -> 0] (*Thanks to Karsten 7*)

enter image description here

Not very general but it is something.

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ One could also use DateObject[isoDateString, TimeZone -> 0] instead of Block[ ... ]. $\endgroup$ – Karsten 7. Jul 24 '17 at 23:56
  • $\begingroup$ @Karsten7. yep, went to far and missed the obvious way. :) $\endgroup$ – Kuba Jul 25 '17 at 6:29
7
$\begingroup$

You really need this as a M DateObject, right? Because if not, you could use Java 8, it has a class ZonedDateTime that guarantees the time zone with the object.

Needs["JLink`"]

ReinstallJava[];

LoadJavaClass["java.time.ZonedDateTime","StaticsVisible"->True];
LoadJavaClass["java.time.ZoneOffset","StaticsVisible"->True];
LoadJavaClass["java.time.format.DateTimeFormatter","StaticsVisible"->True];

timeinutc=ZonedDateTime`now[ZoneOffset`UTC]

timeinutc@toString[]

timeinutc@format[DateTimeFormatter`ISOUINSTANT]

immutable, thread-safe, nano-second precision, ...

https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html

| improve this answer | |
$\endgroup$
  • $\begingroup$ Can you please explain how this works, for those unfamiliar with Java and JLink? For example, toString is not a symbol, so I thought maybe you left out its definition; but no, the code above works, even though toString[] returns unevaluated, and even though timeinutc[] returns just the Java object. $\endgroup$ – 76 Pinto Apr 22 at 21:35
  • $\begingroup$ timeinutc is a pointer into the JVM. So it is a reference to a Java object that resides in the JVM. If you look at Methods@timeinutc, you'll see the toString and format methods listed. Then I call these two methods on the timeinutc object. Yes, to make sense of this one would have to understand that in an object-oriented language (such as Java) we call methods on objects. Not that I recommend learning Java anymore (it's obsolescent), but I do recommend you read a primer on an oo language like Scala. Here as well, we have objects, they have methods, and we call methods on objects. $\endgroup$ – Andreas Lauschke Apr 24 at 1:42
7
$\begingroup$

The repository function FromIsoTimeStamp will correctly parse the Zulu and offset parts of ISO dates. For example:

isoDateString = "2017-04-28T01:50:52.000Z";
ResourceFunction["FromISOTimestamp"][isoDateString]

Correctly returns a GMT date as desired.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.