How to Create a .Net Datetime from Iso 8601 Format

How to create a .NET DateTime from ISO 8601 format

This solution makes use of the DateTimeStyles enumeration, and it also works with Z.

DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);

This prints the solution perfectly.

ISO8601 formatted string to DateTime

Try DateTime time = DateTime.Parse("2016-03-28T16:07:00+0200");. Your string seems to be a format that will be recognized by DateTime.Parse().

C# Datetime ISO 8601 format gives incorrect value

Let me see if my understanding is correct (I'm still not entirely sure when the SOAP comes into play in the question).

You have a UTC DateTime:

var dt = new DateTime(2021, 10, 13, 18, 0, 0, DateTimeKind.Utc);

And you'd like to format that in CST -- which, on October 13, is actually CDT (-05:00)?

If that is correct, then you want to utilise DateTimeOffset, which has a better understanding of.. well, time offsets.

// Your original value. This will have an offset of "00:00" 
// as the DateTime above was created as `DateTimeKind.Utc`
var timeAtUtc = new DateTimeOffset(dt);

// Alternatively:
// var timeAtUtc = new DateTimeOffset(2021, 10, 13, 18, 0, 0, TimeSpan.Zero);

// Find out the correct offset on that day (-5:00)
var cstOffsetAtTheTime = TimeZoneInfo
.FindSystemTimeZoneById("Central Standard Time")
.GetUtcOffset(timeAtUtc);

// And now apply the offset to your original value
var timeAtCst = timeAtUtc.ToOffset(cstOffsetAtTheTime);

// You will now get "2021-10-13T13:00:00-05:00"
// no matter where you run this from.
Console.WriteLine(timeAtCst.ToString("yyyy-MM-ddTHH:mm:sszzz"));

// Edit: If you pass it a date in Feb, you'll see that it will correctly be at -06:00.


Edit 2022-03-07 based on comment below. If you don't need to care about the offset value, you can simply do:

var timeAtUtc = ...;
var timeAtCst = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
timeAtUtc,
"Central Standard Time");

How to parse and generate DateTime objects in ISO 8601 format

The format you're describing is ISO 8601.

Since you're working with timestamps that inclulde a time zone component, I'd strongly recommend using DateTimeOffset instead of DateTime. It makes things so much easier!

To create a DateTimeOffset for a given date, time, and time zone offset, use this syntax:

var date = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-5));
// March 29, 2016 at 12:20:35.93 GMT-5

This code will format a DateTimeOffset as ISO 8601:

public static string FormatIso8601(DateTimeOffset dto)
{
string format = dto.Offset == TimeSpan.Zero
? "yyyy-MM-ddTHH:mm:ss.fffZ"
: "yyyy-MM-ddTHH:mm:ss.fffzzz";

return dto.ToString(format, CultureInfo.InvariantCulture);
}

And, to parse a string back to a DateTimeOffset:

public static DateTimeOffset ParseIso8601(string iso8601String)
{
return DateTimeOffset.ParseExact(
iso8601String,
new string[] { "yyyy-MM-dd'T'HH:mm:ss.FFFK" },
CultureInfo.InvariantCulture,
DateTimeStyles.None);
}

If you must get back to a DateTime you can get this from the DateTimeOffset.UtcDateTime property.

Getting C# to correctly set the Kind property for a parsed ISO 8601 string

Don't use DateTime to parse the string, but use DateTimeOffset. You can then use the LocalDateTime or UtcDateTime property of the generated DateTimeOffset to explicitly get the time represented by the string in local time or UTC time. Or you can use the Offset property to check whether the string did originally contain a timezone offset or not.

c# convert datetime object to iso 8601 string

Observe:

// Your input
DateTime dt = new DateTime(2017, 6, 26, 20, 45, 0, 70, DateTimeKind.Utc);

// ISO8601 with 7 decimal places
string s1 = dt.ToString("o", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.0700000Z"

// ISO8601 with 3 decimal places
string s2 = dt.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.070Z"

A few things:

  • Don't use Z in the format string. That's not a valid format specifier, so it is treated as just a character to output. It will be in every string, regardless of .Kind setting of the input datetime.

  • With DateTime, use K - which properly conveys the .Kind by appending a Z to the output for DateTimeKind.Utc, or an offset from UTC for DateTimeKind.Local, or nothing at all for DateTimeKind.Unspecified.

  • Though T will output as a character because it's not a valid format specifier, I suggest always being explicit about those things, so prefer 'T'.

  • Using fff will always give you back three decimals (milliseconds). If you want the decimals omitted when zero, use FFF instead. Your use of sss is not valid.

  • Passing CultureInfo.InvariantCulture is a good practice, as it helps you avoid problems where the current culture might use a different calendar system. For example ar-SA uses the UmAlQuraCalendar, rather than the proleptic Gregorian calendar required by ISO 8601.

  • In your code you tried, you had called theTime.UtcNow - that won't compile. UtcNow is a static property, not an instance property.

  • Also in your code you called theTime.Date.ToUniveralTime() - Don't do that either. .Date will set the time components to zero, and .ToUniversalTime() will have no effect since the input value already has DateTimeKind.Utc.

Convert ISO time Format To local datetime in vb.net

Your date string is not an "ISO date" as far as I can see. ISO 8601 would lay it out like "2020-05-30T01:52:53+08:00" and .net would parse it with "o"

Parse it by specifying the format:

DateTime.ParseExact("20200530T015253+08", "yyyyMMddTHHmmsszz", Nothing)

If your input data will vary its presentation for time zones that have a fractional hours component such as India being 5.5 hours, then you'll need to vary your format string to zzz

How to create .NET CultureInfo with Dateformat ISO 8601?

It is possible, but only by accessing an internal field via reflection, which is not guaranteed to work in all cases.

var culture = (CultureInfo) CultureInfo.InvariantCulture.Clone();
var field = typeof(DateTimeFormatInfo).GetField("generalLongTimePattern",
BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
// we found the internal field, set it
field.SetValue(culture.DateTimeFormat, "yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK");
}
else
{
// fallback to setting the separate date and time patterns
culture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd";
culture.DateTimeFormat.LongTimePattern = "HH:mm:ss.FFFFFFFK";
}
CultureInfo.CurrentCulture = culture;

Console.WriteLine(DateTime.UtcNow); // "2017-11-07T00:53:36.6922843Z"

Note that the ISO 8601 spec does allow a space to be used instead of a T. It's just preferable to use the T.



Related Topics



Leave a reply



Submit