Where's the Datetime 'Z' Format Specifier

Where's the DateTime 'Z' format specifier?

Maybe the "K" format specifier would be of some use. This is the only one that seems to mention the use of capital "Z".

"Z" is kind of a unique case for DateTimes. The literal "Z" is actually part of the ISO 8601 datetime standard for UTC times. When "Z" (Zulu) is tacked on the end of a time, it indicates that that time is UTC, so really the literal Z is part of the time. This probably creates a few problems for the date format library in .NET, since it's actually a literal, rather than a format specifier.

Converting datetime to z format

Do you mean converting to a string time/date like 2009-06-15 20:45:30Z? If so then try:

mydate.ToUniversalTime().ToString("u");

See http://msdn.microsoft.com/en-us/library/az4se3k1.aspx for info on Standard Date and Time format strings. In particular read the entry on using the "Universal Sortable ("u") Format Specifier" whcih explains why I have the ToUniversalTime call in there.

What is this date format? 2011-08-12T20:17:46.384Z

The T is just a literal to separate the date from the time, and the Z means "zero hour offset" also known as "Zulu time" (UTC). If your strings always have a "Z" you can use:

SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Or using Joda Time, you can use ISODateTimeFormat.dateTime().

what is this 2017-02-06T08:11:24.6728677Z time format? and how can be implemented in jmeter?

The time format in is timestamp for local timezone. The Z stands for timezone.

In JMeter you need to use

${__time(yyyy-MM-dd'T'hh:mm:ssssZ)}

in order to receive the timestamp for current timezone

2017-02-15T12:20:0053+0200

If you want to keep the Z in the date use

${__time(yyyy-MM-dd'T'hh:mm:ssss)}Z

References:

  • Where's the DateTime 'Z' format specifier?

  • https://hellotestworld.com/2016/02/02/cheatsheet-for-jmeter-__time-function-calls/

date format yyyy-MM-ddTHH:mm:ssZ

Using UTC

ISO 8601 (MSDN datetime formats)

Console.WriteLine(DateTime.UtcNow.ToString("s") + "Z");

2009-11-13T10:39:35Z

The Z is there because

If the time is in UTC, add a 'Z'
directly after the time without a
space. 'Z' is the zone designator for
the zero UTC offset. "09:30 UTC" is
therefore represented as "09:30Z" or
"0930Z". "14:45:15 UTC" would be
"14:45:15Z" or "144515Z".

If you want to include an offset

int hours = TimeZoneInfo.Local.BaseUtcOffset.Hours;
string offset = string.Format("{0}{1}",((hours >0)? "+" :""),hours.ToString("00"));
string isoformat = DateTime.Now.ToString("s") + offset;
Console.WriteLine(isoformat);

Two things to note: + or - is needed after the time but obviously + doesn't show on positive numbers. According to wikipedia the offset can be in +hh format or +hh:mm. I've kept to just hours.

As far as I know, RFC1123 (HTTP date, the "u" formatter) isn't meant to give time zone offsets. All times are intended to be GMT/UTC.

Why does format specifier U alter the value of DateTime?

As you may read here The Universal Sortable ("u") Format Specifier

no conversion of the original DateTime value is performed

And here The Universal Full ("U") Format Specifier

value is automatically converted to UTC

So for test 2 and 3 assert against tim.ToUniversalTime().

C# DateTime.ToString with zzz breaks in dotnet framework but not in dotnet core

No, it's behaving as documented. From the documentation of the zzz format specifier (emphasis mine):

With DateTime values, the "zzz" custom format specifier represents the signed offset of the local operating system's time zone from UTC, measured in hours and minutes. It doesn't reflect the value of an instance's DateTime.Kind property. For this reason, the "zzz" format specifier is not recommended for use with DateTime values.

Arguably that's unfortunate, but it's not a bug.

Note that .NET Core (and .NET 5.0) apparently doesn't behave as documented. While you could argue it's "fixed" in .NET Core, I'd suggest that behaving in an undocumented way is a bug in itself, and one that could make code migration harder than expected.

I suggest you follow the recommendation in the docs, and avoid using zzz with DateTime values. I'd also suggest using my Noda Time library instead, where there isn't the ambiguity in terms of a value "maybe being local, or maybe being UTC", but that's a slightly different matter. (I wouldn't expect you to run into this problem using Noda Time, and your other date/time code would hopefully be clearer.)

DateTime: Custom format specifier

You can implement custom format specifiers with the letters and tokens you want for new types that you implement.

But you cannot change the acceptable format tokens for built-in types, like DateTime.

Take a look at this documentation.

Please note that what Microsoft calls Custom Format Specifiers, in this context, means combining the acceptable format tokens for DateTime as you wish, together with CultureInfo stuff.

You can check in the reference source how DateTime uses internally the class DateTimeFormat, that has a fixed set of tokens it accepts.

You best approach, I believe, is to write a method that gets the string and substitutes "WW" by ISOWeek.GetWeekOfYear(date)

Other options are:

  • Write an extension method for your convenience
  • Create a custom type implementing IFormattable with conversions to DateTime, overload operators and stuff... so much trouble, not worth it.

By the way, Custom DateTime Format Specifiers were introduced in c#6.

Use format specifier with CultureInfo.CurrentCulture

try the following:

string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:G} {0:zzz}", myDateTimeOffset);

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");


Related Topics



Leave a reply



Submit