What does the 'Z' mean in Unix timestamp '120314170138Z'? - timezone

I have an X.509 certificate which has the following 2 timestamps:
['validFrom'] = String(13) "120314165227Z"
['validTo'] = String(13) "130314165227Z"
What does the postfix character 'Z' mean. Does it specify the timezone?

Yes. 'Z' stands for Zulu time, which is also GMT and UTC.
From http://en.wikipedia.org/wiki/Coordinated_Universal_Time:
The UTC time zone is sometimes denoted by the letter Z—a reference to
the equivalent nautical time zone (GMT), which has been denoted by a Z
since about 1950. The letter also refers to the "zone description" of
zero hours, which has been used since 1920 (see time zone history).
Since the NATO phonetic alphabet and amateur radio word for Z is
"Zulu", UTC is sometimes known as Zulu time.
Technically, because the definition of nautical time zones is based on longitudinal position, the Z time is not exactly identical to the actual GMT time 'zone'. However, since it is primarily used as a reference time, it doesn't matter what area of Earth it applies to as long as everyone uses the same reference.
From wikipedia again, http://en.wikipedia.org/wiki/Nautical_time:
Around 1950, a letter suffix was added to the zone description,
assigning Z to the zero zone, and A–M (except J) to the east and N–Y
to the west (J may be assigned to local time in non-nautical
applications; zones M and Y have the same clock time but differ by 24
hours: a full day). These were to be vocalized using a phonetic
alphabet which pronounces the letter Z as Zulu, leading sometimes to
the use of the term "Zulu Time". The Greenwich time zone runs from
7.5°W to 7.5°E longitude, while zone A runs from 7.5°E to 22.5°E longitude, etc.

"Z" doesn't stand for "Zulu"
I don't have any more information than the Wikipedia article cited by the two existing answers, but I believe the interpretation that "Z" stands for "Zulu" is incorrect. UTC time is referred to as "Zulu time" because of the use of Z to identify it, not the other way around. The "Z" seems to have been used to mark the time zone as the "zero zone", in which case "Z" unsurprisingly stands for "zero" (assuming the following information from Wikipedia is accurate):
Around 1950, a letter suffix was added to the zone description, assigning Z to the zero zone, and A–M (except J) to the east and N–Y to the west (J may be assigned to local time in non-nautical applications — zones M and Y have the same clock time but differ by 24 hours: a full day). These can be vocalized using the NATO phonetic alphabet which pronounces the letter Z as Zulu, leading to the use of the term "Zulu Time" for Greenwich Mean Time, or UT1 from January 1, 1972 onward.

The Z stands for 'Zulu' - your times are in UTC. From Wikipedia:
The UTC time zone is sometimes denoted by the letter Z—a reference to the equivalent nautical time zone (GMT), which has been denoted by a Z since about 1950. The letter also refers to the "zone description" of zero hours, which has been used since 1920 (see time zone history). Since the NATO phonetic alphabet and amateur radio word for Z is "Zulu", UTC is sometimes known as Zulu time. This is especially true in aviation, where Zulu is the universal standard.

Related

Cannot parse string to time with timezone offset included RFC3339 with seemingly contradictory errors

I am using Golang and time.Time to Parse a given string into a time object.
Using RFC3339 and time.Parse here is an example of my code:
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z07:00")
if err != nil {
return nil, err
}
I get the follow errors.
When I include timezone offset I am getting:
ERRO[0002] parsing time "2020-08-08T00:22:44Z07:00": extra text: 07:00
When I don't include the timezone offset I am getting:
ERRO[0002] parsing time "2020-08-08T00:15:36" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"
How do I avoid this issue when parsing time into a structured object?
The presence of the character Z in the Go time.RFC3339 constant "2006-01-02T15:04:05Z07:00" does not mean that a date conforming to the pattern is supposed to include a Z followed by the time zone offset.
In fact, a date with Z followed by anything else is not a valid RFC3339 date. Hence, your first error extra text: 07:00
The Z stands for "Zulu Time", i.e. UTC time zone. From the RFC3339 specs:
Z A suffix which, when applied to a time, denotes a UTC
offset of 00:00; often spoken "Zulu" from the ICAO
phonetic alphabet representation of the letter "Z".
So the Z alone is already providing the time zone information, that is, UTC.
As #Flimzy noted in the comments, 2020-08-08T00:22:44Z would be a valid RFC3339 date.
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z")
if err != nil {
panic(err)
}
fmt.Println(t) // 2020-08-08 00:22:44 +0000 UTC
Now, if you read the RFC3339 standard further, you see this definition:
time-zone = "Z" / time-numoffset
time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
Which means that the time zone part of the date is either a Z or the offset. Clearly, since the Z already represents the offset 00:00, you can't have one more +/-HH:mm offset in the same date string.
But this also means that Z or the +/-HH:mm must be present. So if you remove both of them, you get your second error: cannot parse "" as "Z07:00"
The parser is attempting to read the "2020-08-08T00:15:36" string as RFC3339 so it expects either a Z or an offset after the seconds (or milliseconds, if any).
In conclusion, the Z07:00 in the Go time.RFC3339 pattern is just a representation of the fact that the date string is supposed to include a time zone. A valid RFC3339 date string must include either Z or the offset.

Why can't go parse the time represented by the provided formats?

Consider this example:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Parse(time.RFC3339, time.RFC3339))
}
The output is:
0001-01-01 00:00:00 +0000 UTC parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00
Why can't time.Parse() handle a layout as a value? What's missing here?
UPDATE: Cutting off the time zone value (but not the 'Z' delimiting the time from the zone) fixes it:
fmt.Println(time.Parse(time.RFC3339, "2015-09-15T11:50:00Z"))
Why can't time.Parse() handle time zone info when using time.RFC3339 as the layout string?
http://play.golang.org/p/p3fHfJNHVK
UPDATE: JimB's answer led me to read from RFC3339 and I found these examples that clarify further:
Here are some examples of Internet date/time format.
1985-04-12T23:20:50.52Z
This represents 20 minutes and 50.52 seconds after the 23rd hour of
April 12th, 1985 in UTC.
1996-12-19T16:39:57-08:00
This represents 39 minutes and 57 seconds after the 16th hour of
December 19th, 1996 with an offset of -08:00 from UTC (Pacific
Standard Time). Note that this is equivalent to 1996-12-20T00:39:57Z
in UTC.
The time.RFC3339 format is a case where the format string itself isn't a valid time. You can't have a Z and an offset in the time string, but the format string has both because the spec can contain either type of timezone specification.
Both of these are valid RFC3339 times:
"2015-09-15T14:00:12-00:00"
"2015-09-15T14:00:13Z"
And the time package needs to be able to parse them both using the same RFC3339 format string.
As noted, 2006-01-02T15:04:05Z07:00 is an invalid IETF RFC-3339 time format. Here's an explanation.
The reason you cannot have both Z and an offset is that they are both ways to represent a time offset. Z is equivalent to +00:00 indicating a zero hour/minute offset, or no offset. You cannot say both +00:00 offset and +07:00 offset in the same time representation.
The following is the Z definition in the RFC-3339 Section 2:
https://www.rfc-editor.org/rfc/rfc3339#section-2
Z A suffix which, when applied to a time, denotes a UTC
offset of 00:00; often spoken "Zulu" from the ICAO
phonetic alphabet representation of the letter "Z".
Of note, while Z is equivalent to +00:00, they are both different from -00:00 which indicates known UTC time with an unknown offset, as described in RFC-3339 Section 4.3:
https://www.rfc-editor.org/rfc/rfc3339#section-4.3
4.3. Unknown Local Offset Convention
If the time in UTC is known, but the offset to local time is unknown,
this can be represented with an offset of "-00:00". This differs
semantically from an offset of "Z" or "+00:00", which imply that UTC
is the preferred reference point for the specified time. RFC2822
[IMAIL-UPDATE] describes a similar convention for email.

what's this date format ? 2006-09-01T07:00:00.000+0000 ? is it ISO_8601 ?

I am working on REST calls where I need to send date in "2006-09-01T07:00:00.000+0000" format.
User enters date in "YYYY/MM/DD" format and I am using "moment.js" to format the date in ISO 8601 using this format "YYYY-MM-DDTHH:MM:SS.MMMZ" . But it gives me this output "1969-06-20T00:06:00.Jun-07:00".
So, how do I get date in this format "2006-09-01T07:00:00.000+0000" using moment.js OR Javascript ?
Yes, it is ISO 8601. 2006-09-01T07:00:00.000+0000 is the first day of the ninth month of the year 2006, 7 hours, 0 minutes, 0.000 seconds offset 0 hours from UTC. Whether or not decimals are allowed is up to the parties exchanging dates (which is a fancy way of ISO saying "it's optional").
4.2.2.4 Representations with decimal fraction
If necessary for a particular application a decimal fraction of hour, minute or second may be included. If a decimal fraction is included, lower order time elements (if any) shall be omitted and the decimal fraction shall be divided from the integer part by the decimal sign specified in ISO 31-0, i.e. the comma [,] or full stop [.]. Of these, the comma is the preferred sign. If the magnitude of the number is less than unity, the decimal sign shall be preceded by two zeros in accordance with 3.6.
The interchange parties, dependent upon the application, shall agree the number of digits in the decimal fraction. The format shall be [hhmmss,ss], [hhmm,mm] or [hh,hh] as appropriate (hour minute second, hour minute, and hour, respectively), with as many digits as necessary following the decimal sign. A decimal fraction shall have at least one digit. In the examples below it has been agreed to give the smallest time element a decimal fraction with one digit.
(As pointed out by #chansen, technically it should be 2006-09-01T07:00:00.000+00:00 with a separator on the time zone because according to 4.3.3(d) every part must use either the basic format (no separators) or the extended format (with separators), but nobody bothers with that, strptime can't produce that format, and you'll probably break some ISO 8601 parsers).
Outputting this is covered in other answers for both Javascript and moment.js.
Javascript has Date.toISOString for output. Date.new will also accept an ISO 8601 string. Every recent browser should support it, though Internet Explorer only added it in version 9 (IE 8 still represents 5% of desktop users).
Here's the moment.js docs on String formatting. YYYY-MM-DDTHH:MM:SS.MMMZ is incorrect because you're using M to mean three different things. What you want is YYYY-MM-DDTHH:mm:ss.SSSZZ.
YYYY - year
MM - month number (2 digit)
DD - day of month (2 digit)
HH - hours (2 digit, 24 hour format)
mm - minutes (2 digit)
ss - seconds (2 digit)
SSS - thousands of seconds
ZZ - UTC offset
The format that worked for me for 2006-09-01T07:00:00.000+0000
was: yyyy-MM-dd'T'hh:mm:ss.sssZ

In what format is this date string?

Im trying to convert a bunch of NSStrings into NSDate objects. Here is an example string:
2013-04-25T15:51:30.427+1.00
But I can't figure out what format it is in, so far I have (The question marks are the bits I'm stumped with):
yyyy-MM-ddTHH:mm:ss????zzz
The main problem I'm having is with the '.427' part although if I'm making a mistake elsewhere, let me know :)
Does anyone have any ideas? Or could point me to a list of all the possible date format specifiers? I found this: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx which is useful but it doesn't appear to have any specifier for the '.427' part that I'm stuck on.
Any help is appreciated, Thanks.
The proper format is yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ.
See Unicode Date Format Patterns.
Also, the ZZZZZ format for the +00:00 timezone format was added to iOS 6 and is not supported under iOS 5 or earlier.
It is a valid date format as specified by ISO 8601, according to W3
The formats are as follows. Exactly the components shown here must be
present, with exactly this punctuation. Note that the "T" appears
literally in the string, to indicate the beginning of the time
element, as specified in ISO 8601.
Year:
YYYY (eg 1997) Year and month:
YYYY-MM (eg 1997-07) Complete date:
YYYY-MM-DD (eg 1997-07-16) Complete date plus hours and minutes:
YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) Complete date plus hours, minutes and seconds:
YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) Complete date plus hours, minutes, seconds and a decimal fraction of a
second
YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
where:
YYYY = four-digit year
MM = two-digit month (01=January, etc.)
DD = two-digit day of month (01 through 31)
hh = two digits of hour (00 through 23) (am/pm NOT allowed)
mm = two digits of minute (00 through 59)
ss = two digits of second (00 through 59)
s = one or more digits representing a decimal fraction of a second
TZD = time zone designator (Z or +hh:mm or -hh:mm)
In your case, the date has millisecond accuracy, try adding .sss to the format

Format with leading zeros in Erlang

I would like to return the local time as string but with leading zeros. I tried this:
{{Year, Month, Day}, {Hour, Minute, Second}} = erlang:localtime().
DateAsString = io_lib:format("~2.10.0B~2.10.0B~4.10.0B~2.10.0B~2.10.0B~2.10.0B",
[Month, Day, Year, Hour, Minute, Second]).
But if some of the components is one digit, the returned string is:
[["0",57],"29","2011","17","33","34"]
The current month 9 is printed as ["0",57].
Please, help.
Thank you.
Try:
1> lists:flatten([["0",57],"29","2011","17","33","34"]).
"09292011173334"
io_lib:format/2 (and it's companion io:format/2) actually returns a deep IO list. Such a list is printable and can be sent on a socket or written to a file just as a flat string, but is more efficient to produce. Flattening is often useless, because in all cases where the string will be printed or output to a file/socket it will automatically be flattened by Erlang.
You want to be using something like this:
DateAsString = io_lib:format("~2..0w~2..0w~4..0w~2..0w~2..0w~2..0w",
[Month, Day, Year, Hour, Minute, Second]).
The more common w format modifier does the right thing here, what with base and such, so there's no need to use the more complex B modifier. 2..0 says "2 characters wide, zero padded, no precision specified." We don't need precision here, since we're dealing with integers.

Resources