{"id":250,"date":"2024-10-29T11:17:22","date_gmt":"2024-10-29T03:17:22","guid":{"rendered":"http:\/\/samba.newstrong.me:56657\/?p=250"},"modified":"2024-10-29T11:17:22","modified_gmt":"2024-10-29T03:17:22","slug":"zoneddatetime-tostring-compatability-with-iso-8601","status":"publish","type":"post","link":"https:\/\/newstrong.top\/index.php\/2024\/10\/29\/zoneddatetime-tostring-compatability-with-iso-8601\/","title":{"rendered":"ZonedDateTime toString compatability with ISO 8601"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/cylc.github.io\/cylc-doc\/stable\/html\/_images\/iso8601-dates.svg\" alt=\"iso8601\" \/><\/p>\n<blockquote>\n<p>I am trying to ensure that calling toString() on my ZonedDateTime Object will comply with ISO-8601 format.<br \/>\nThe documentation for the toString() method states:<br \/>\n&#8230;The output is compatible with ISO-8601 if the offset and ID are the same<br \/>\nDoes this mean that there exists a situation where calling zdt.getOffset() will return something different than zdt.getZone().getRules().getOffset(zdt.toInstant()) ?<br \/>\nThis doesn&#8217;t seem to make sense.<br \/>\nCan someone provide an example in which the offset and ID are not the same (ie: where toString() does not comply with ISO-8601) so that I can better understand the description in the documentation.<\/p>\n<\/blockquote>\n<h2>Best Answer<\/h2>\n<p>The example in the documentation is 2007-12-03T10:15:30+01:00[Europe\/Paris]. This happens not to be ISO compliant since ISO-8601 does not include the [Europe\/Paris] part. This was added by the java.time developers in a compromise between getting as close to the standard as reasonable and still provding the time zone information in an unambiguous way.<\/p>\n<p>So the real question may in fact be the opposite: if ZonedDateTime.toString() includes the time zone information that ISO does not include, when is the result fully ISO compliant? What does \u201cif the offset and ID are the same\u201d mean? Here we have to remember that ZoneOffset is a subclass of ZoneID and may be used as a zone ID in ZonedDateTime. In this case the offset and the ID are the same. Otherwise they are not. For a specific example, ZonedDateTime.now(ZoneOffset.ofHours(+2)).toString() may produce 2017-04-26T15:04:59.828+02:00. This is fully ISO compatible because the zone is given as just +02:00, which is the same as the offset. Also ZonedDateTime.now(ZoneOffset.UTC).toString() gives something in the format 2017-04-26T13:04:59.828Z. Since Z counts as an offset, this is compatible too.<\/p>\n<p>I think that in most cases it won\u2019t be very useful. If your zone is just an offset, you would usually prefer to use OffsetDateTime over ZonedDateTime, and if so, of course you don\u2019t care whether ZonedDateTime.toString() is ISO compatible or not<\/p>\n<h2>Date Reference Util Function<\/h2>\n<pre><code class=\"language-java\">fun Long.toInstant(): Instant {\n  return Instant.ofEpochMilli(this)\n}\n\nfun Instant.toCurrentZonedDateTime(zoneId: ZoneId = ZoneId.systemDefault()): ZonedDateTime {\n  return ZonedDateTime.ofInstant(this, zoneId)\n}\n\nfun Instant.toSgZonedDateTime(): ZonedDateTime {\n  return ZonedDateTime.ofInstant(this, ZoneId.of((&quot;Asia\/Singapore&quot;)))\n}\n\nfun Instant.toUTCDateTime(): ZonedDateTime {\n  return this.toCurrentZonedDateTime(zoneId = ZoneOffset.UTC)\n}\n\nfun ZonedDateTime.toStandardISO8601(): String {\n  return this.withZoneSameInstant(ZoneOffset.UTC).toString()\n}\n\nfun ZonedDateTime.toSingaporeStandardISO8601IgnoreUTCZoneId(): String {\n  return ZonedDateTime.of(this.toLocalDateTime(), ZoneId.of(&quot;Asia\/Singapore&quot;)).toStandardISO8601()\n}\n\nfun ZonedDateTime.toSingaporeZoneDateTime(): ZonedDateTime {\n  return this.withZoneSameInstant(ZoneId.of(&quot;Asia\/Singapore&quot;))\n}\n\nfun String?.parseStandardISO8601(formatter: DateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME): ZonedDateTime? {\n  if (this == null) return null\n  return try {\n    ZonedDateTime.parse(this, formatter)\n  } catch (e: Exception) {\n    null\n  }\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I am trying to ensure that calling toString() on my Zon&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":71,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-250","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/posts\/250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/comments?post=250"}],"version-history":[{"count":0,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/posts\/250\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/media\/71"}],"wp:attachment":[{"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/media?parent=250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/categories?post=250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/newstrong.top\/index.php\/wp-json\/wp\/v2\/tags?post=250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}