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.
LocalDateTime
DateTimeZone
LocalDateTime
to a ZonedDateTime
ZonedDateTime
to an OffsetDateTime
How do we do it with fewer steps?
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.
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.
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!
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 .
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With