Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output an ISO 8601 string

Tags:

c#

.net

nodatime

How do we create a date/time in a specific timezone and output a short ISO 8601 date/time with offset from UTC? For instance, 5 PM Pacific Standard Time on 08 September 2015 must look like this:

2015-09-08T17:00:00-07:00

Here is my current attempt.

using System;
using NodaTime;
using NodaTime.Text;

namespace ConsoleApplication1_Nodatime
{
    class Program
    {
        public static void Log(string x) => Console.WriteLine(x);
        public static void Read() => Console.ReadLine();

        static void Main(string[] args)
        {
            var localDateTime = new LocalDateTime(2015, 09, 08, 17, 0);
            var zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/Vancouver");
            var zonedDateTime = localDateTime.InZoneStrictly(zone);
            Log(zonedDateTime.ToOffsetDateTime().ToString());
            Read();
        }
    }
}

This works, though seems like too many steps.

  1. Create a LocalDateTime
  2. Create a DateTimeZone
  3. Convert the LocalDateTime to a ZonedDateTime
  4. Convert the ZonedDateTime to an OffsetDateTime

How do we do it with fewer steps?

like image 572
Shaun Luttin Avatar asked Sep 25 '15 02:09

Shaun Luttin


People also ask

How do I convert a date to ISO 8601?

toISOString() method is used to convert the given date object's contents into a string in ISO format (ISO 8601) i.e, in the form of (YYYY-MM-DDTHH:mm:ss. sssZ or ±YYYYYY-MM-DDTHH:mm:ss. sssZ). The date object is created using date() constructor.

How do I print the date in an ISO file?

Here as we know that ISO format is YYYY-MM-DD so we convert it into this format by using the following format code- “%Y-%m-%dT%H:%M:%S.

How do I convert ISO to timestamp?

Use the getTime() method to convert an ISO date to a timestamp, e.g. new Date(isoStr). getTime() . The getTime method returns the number of milliseconds since the Unix Epoch and always uses UTC for time representation. Copied!

Is ISO 8601 always UTC?

Date.prototype.toISOString() The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 characters long ( YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ , respectively). The timezone is always zero UTC offset, as denoted by the suffix Z .


1 Answers

As noted in the comments of the question, you only need a ZonedDateTime in order to achieve your desired formatting (no need for the OffsetDateTime). The format string passes the "general" offset pattern so that the minutes should be included ("medium format") only if the offset has minutes.

zonedDateTime.ToString(
    "yyyy-MM-ddTHH:mm:sso<g>", 
    System.Globalization.CultureInfo.InvariantCulture)

For brevity, here are the available offset patterns documented:

  • f: Full format, displaying all information including fractional seconds. Typical pattern text: +HH:mm:ss.fff
  • l: Long format, displaying information down to the second. Typical pattern text: +HH:mm:ss
  • m: Medium format, displaying information down to the minute. Typical pattern text: +HH:mm
  • s: Short format, displaying information down to the hour. Typical pattern text: +HH
  • g: General pattern. Formatting depends on the value passed in:
    • If the offset has fractional seconds, the full format is used; otherwise
    • If the offset has seconds, the long format is used; otherwise
    • If the offset has minutes, the medium format is used; otherwise
    • The short format is used When parsing, the other standard format patterns are tried one at a time. This is the default format pattern.
  • G: As g, but using Z for an offset of 0, as if it were Z-prefixed.

Source: http://nodatime.org/1.3.x/userguide/offset-patterns.html

ORIGINAL QUESTION

With the original request to format as ISO-8601 always showing the trailing minutes, you can use the custom format string below. By default, it meets ISO-8601 standards which does not require the trailing ":00". However, you can pass an offset pattern to force the formatting you are wanting:

zonedDateTime.ToString(
    "yyyy-MM-ddTHH:mm:sso<m>", 
    System.Globalization.CultureInfo.InvariantCulture)

Source: http://nodatime.org/1.3.x/userguide/offset-patterns.html

UPDATE TO SHORTEN CODE

If you're just looking to shorten code, you can always wrap the code in a helper method - possibly even as a static extension method.

public static class NodaTimeHelpers
{
    public static Lazy<DateTimeZone> Zone = new Lazy<DateTimeZone>(
        () => DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/Vancouver"));
    public static string ToStringWithOffset(this LocalDateTime localDateTime)
    {
        if (localDateTime == null)
            return "";
        var zonedDateTime = localDateTime.InZoneStrictly(Zone.Value);
        return zonedDateTime.ToString(
            "yyyy-MM-ddTHH:mm:sso<g>",
            System.Globalization.CultureInfo.InvariantCulture);
    }
}

This allows your local date time object to convert to string very easily:

localDateTime.ToStringWithOffset();
like image 60
Jason W Avatar answered Sep 20 '22 17:09

Jason W