Reputation: 1621
I have ZonedDateTime value. I need to obtain corresponding UTC time and to format it as ISO8601 string (without Time Zone). What's the right "NodaTime way" of doing it?
I understand that I can use ZonedDateTime.ToDateTimeUtc()
method to get .Net DateTime
Kind of Utc. Should I do it and then just use ToString()
?
Like
var myresult = resZonedDateTime.ToDateTimeUtc().ToString("s")
Should I really use "s" there?
Upvotes: 4
Views: 5299
Reputation: 241485
There are a few different ways, depending on exactly what you're looking for.
First, you need to decide whether you want a value like 2014-10-30T16:46:49
or one like 2014-10-30T16:46:49Z
. Both are allowed by ISO8601, but the trailing Z
at the end is specifically used when the value is UTC. If you send the string elsewhere, the receiving party will not have to guess what the basis for the value is.
If you want the Z
, then convert your ZonedDateTime
to an Instant
using the .ToInstant()
method.
Instant instant = zdt.ToInstant();
If you don't want the Z
, but still want the value to reflect UTC, then adjust your ZonedDateTime
to UTC, then strip it down to the LocalDateTime
using it's .LocalDateTime
property.
LocalDateTime ldt = zdt.WithZone(DateTimeZone.Utc).LocalDateTime;
Next, you need to decide whether you want to format the string inline with the BCL-based API, or whether you want to use the pattern-based API. Noda Time supports both, which you can read about in the user guide.
The BCL-based API allows you to use methods you're already familiar with, such as .ToString()
and .ToString("some format", someCulture)
For example:
string s = instant.ToString();
or
string s = ldt.ToString("s", CultureInfo.InvariantCulture);
The pattern-based API separates the work of parsing the format string from doing the actual formatting, as two steps:
var pattern = InstantPattern.ExtendedIsoPattern;
var s = pattern.Format(instant);
It is much more efficient if you are going to be formatting many items. I typically use it when I'm working with LINQ. For example:
var pattern = InstantPattern.GeneralPattern;
var strings = instants.Select(pattern.Format);
or
var pattern = LocalDateTimePattern.GeneralIsoPattern;
var strings = ldts.Select(pattern.Format);
And finally, you need to think about the precision you want. In the pattern API, the "general" formats are precise to whole seconds. The "extended" formats include fractional seconds up to 7 decimal places. You could also create your own pattern using the Create...
static methods on the various pattern classes.
If you are just using ToString
, then keep in mind that the default format may or may not be what you are looking for. Again, you can pass a format string. For Instant
values, "g"
is precise to whole seconds, but you would use a custom string of "yyyy'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFF'Z'"
if you need precision. For LocalDateTime
values, "s"
is precise to whole seconds, and "o"
is precise to 7 decimals.
Again, all of this is in the "Text" chapter of the user guide, which I would encourage you to read.
Upvotes: 11