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
, useK
- which properly conveys the.Kind
by appending aZ
to the output forDateTimeKind.Utc
, or an offset from UTC forDateTimeKind.Local
, or nothing at all forDateTimeKind.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, useFFF
instead. Your use ofsss
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 examplear-SA
uses theUmAlQuraCalendar
, 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 hasDateTimeKind.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
How to Detect If I'm Running in Mono-Service
How to Get the Full Path of Running Process
Any Decent C# Profilers Out There
Unity Game Manager. Script Works Only One Time
How to Elevate Privileges Only When Required
Efficient Way to Remove All Whitespace from String
Puzzling Enumerable.Cast Invalidcastexception
Download/Stream File from Url - ASP.NET
How to Tell a Lambda Function to Capture a Copy Instead of a Reference in C#
How to Create a .Net Datetime from Iso 8601 Format
C# - Multiple Generic Types in One List
Prevent Caching in ASP.NET MVC for Specific Actions Using an Attribute
Difference Between Console.Read() and Console.Readline()