How do I parse an ISO 8601 Timestamp in Go? - go

I know I need to use a time layout in Go (as shown here https://golang.org/src/time/format.go) but I can't find the layout for an ISO 8601 timestamp.
If it helps, I get the timestamp from the Facebook API. Here is an example timestamp: 2016-07-25T02:22:33+0000

I found this layout to work: "2006-01-02T15:04:05-0700"

The problem here is that RFC3339 requires the zone offset to be given as "+00:00" (or "Z" in case of UTC) while ISO8601 allows it to be "+0000".
From RFC3339:
[...]
time-numoffset = ("+" / "-") time-hour ":" time-minute
time-offset = "Z" / time-numoffset
[...]
full-time = partial-time time-offset
date-time = full-date "T" full-time
So instead of the time.RFC3339 layout
"2006-01-02T15:04:05Z07:00"
you have to use:
"2006-01-02T15:04:05Z0700"

RFC3339 is equivalent to ISO 8601. Specifically, it has identical format, RFC3339 just has stricter requirements (example, it requires a complete date representation with 4-digit year).
What's the difference between ISO 8601 and RFC 3339 Date Formats?
So you can use the constant time.RFC3339 as your layout.

You have that to use the some layout of your date.
data := "2022-01-24T00:00:00.000-03:00"
layout := "2006-01-02T15:04:05.000-03:00"
dataTime, err := time.Parse(layout, data)

Related

convert Calendar date to Julian Date in Unix

I have one requirement. in one of the source file I'm getting calendar date as input and while processing the file it has to convert Julian Date format. I just need a Script.
ex:Date: 10-Nov-2020
Julian Date: 2020314
The easiest way is
date -d 10-Nov-2020 +%Y%j
but it seems to count from 1, not 0, so it returns 2020315.
Perl's Time::Piece can be used to get the expected value:
perl -MTime::Piece -lwe '$t = localtime->strptime(shift, "%d-%b-%Y"); print $t->year, $t->yday' -- 10-Nov-2020
You might need sprintf "%03d", $t->yday instead of just $t->yday if you want 2020000 instead of 20200 for the first day.

Parsing date is giving error: month out of range in Go

I have a date:
myStringDate = "27-09-2019"
that is a string, and I need to convert to time.Time in Go.
So, I do:
date, err = time.Parse("01-02-2006", myStringDate)
And I get an error:
data:<*time.ParseError>(0xc000098140)
:<time.ParseError>
Layout:"01-02-2006"
Value:"27-09-2019"
LayoutElem:"01"
ValueElem:"-09-2019"
Message:": month out of range"
Nevertheless, the layout I use to parse it seems OK.
I am parsing several files, all coming from the same sources, and the other file can be parsed without any problems
What point am I missing ?
Per the documentation, the layout parameter to Parse is the canonical date "Mon Jan 2 15:04:05 -0700 MST 2006" represented in the desired format. That means the layout you gave is MM-DD-YYYY, when your data appears to be DD-MM-YYYY. If that is the case, your layout string should be 02-01-2006.
myStringDate := "27-09-2019"
date, err := time.Parse("02-01-2006", myStringDate)
https://play.golang.org/p/qUEDtcG1v3W

ISO 8601 date-time format combining 'Z' and offset of '+0000'

I'm playing with date-time format from ISO 8601. I have this pattern:
"yyyy-MM-dd'T'HH:mm:ssZZ'Z'"
and the output is:
"2015-11-17T00:00:00+0000Z"
My question is if the output is ok, if is possible to have in a date +0000 and Z taking in account both has the same meaning time zone offset/id. Thanks in advance for clarification =)
No, not OK
No, the Z is an offset-from-UTC so it should not be combined redundantly with a numerical offset of +00:00 or +0000.
ISO 8601
While I do not have access to a paid copy of the ISO 8601 spec, the Wikipedia page clearly states that the Z must follow the time-of-day:
…add a Z directly after the time without a space.
IETF RFC 3339
The freely-available RFC 3339, a profile of ISO 8601, defines a Z as being attached to a time-of-day:
A suffix … applied to a time …
The RFC also states with formal ABNF notation that we should use either a Z or a number. In ABNF, the slash (SOLIDUS) means “or” (exclusive ‘or’), while the pair of square brackets means “optional”.
time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
time-zone = "Z" / time-numoffset
Furthermore, section 5.4 of the spec specifically recommends against including redundant information.
Java
The modern java.time classes built into Java use the standard ISO 8601 formats by default when parsing/generating strings. See Oracle Tutorial.
Parsing text input
With Z:
Instant instant = Instant.parse( "2019-01-23T12:34:56.123456789Z" ) ;
With +00:00:
OffsetDateTime odt = OffsetDateTime.parse( "2019-01-23T12:34:56.123456789+00:00" ) ;
Generating text output
To create a string with the Z, simply call Instant::toString.
String output = Instant.now().toString() ; // Capture the current moment in UTC, then generate text representing that value in standard ISO 8601 using the `Z` offset-indicator.
2019-05-22T21:00:52.214709Z
To create a string with the 00:00, call OffsetDateTime::format. Generate text using a DateTimeFormatter with a formatting pattern you define.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSxxx" ) ;
String output = OffsetDateTime.now( ZoneOffset.UTC ).format( f ) ;
2019-05-22T21:00:52.319076+00:00
Truncating
You may want to truncate any microseconds or nanoseconds.
Instant
.now()
.truncatedTo( ChronoUnit.MILLIS )
.toString()
2019-05-22T21:11:28.970Z
…and…
OffsetDateTime
.now( ZoneOffset.UTC )
.truncatedTo( ChronoUnit.MILLIS )
.format(
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSxxx" )
)
2019-05-22T21:11:29.078+00:00
See this code running live at IdeOne.com.

What kind of date format is this and how do I transform it?

Making a GET request to a private (no public documentation) API returns data in JSON format.
The value for date looks as follows:
AanmeldDatum: "/Date(1262300400000+0100)/"
There's another variable called AangebodenSindsTekst which means OfferedSinceText and it's value is "8 augustus 2014". So the unknown Date format should get parsed into that specific value.
I'm wondering what kind of date format it is and how can I transform this to something like this 2014-08-08 with Ruby?
I've tried this:
require 'time'
t = '1262300400000+0100'
t2 = Time.parse(t)
# => ArgumentError: no time information in "1262300400000+0100"
Ruby's Time class is your friend, especially the strptime method:
require 'time'
foo = Time.strptime('1262300400000+0100', '%N') # => 2014-08-08 16:57:25 -0700
foo = Time.strptime('1262300400000+0100', '%N%z') # => 2014-08-08 08:57:25 -0700
%N tells Ruby to use nanoseconds. It's throwing away the precision after the 9th digit which is OK if you don't need the rest of the value. Nanosecond accuracy is good enough for most of us.
%z tells Ruby to find the timezone offset, which it then applies to the returned value.
While parse can often figure out how to tear apart an incoming string, it's not bullet-proof, nor is it all-knowing. For speed, I'd recommend learning and relying on strptime if your strings are consistent.
As the Tin Man pointed out in this answer, use the following instead:
Time.strptime('1262300400000+0100', '%Q%z')
it could be milliseconds since epoc, take off the last 3 zeros and plug it into a unix time stamp converter, comes out as Dec 31st 2009
TIME STAMP: 1262300400
DATE (M/D/Y # h:m:s): 12 / 31 / 09 # 11:00:00pm UTC

Ruby local_to_utc returns invalid year

I have the following date string ('US/Eastern'), which I need to convert to UTC:
date_src = '2014-07-07T23:10:00+0'
First I convert it to a "valid" format so I can operate it on later processes. I use the following to have an iso version of the date:
date = DateTime.parse(date_src).iso8601
At this point date is a nice '2014-07-07T23:10:00+00:00'. The last step on my process is to translate this date to UTC. I'm using the following:
TZInfo::Timezone.get('US/Eastern').local_to_utc(date)
The problem is this is giving me 20014 as output, instead of the UTC version of the original date. If I try:
TZInfo::Timezone.get('UTC').local_to_utc(date)
I get 2014, which is the correct year but still unexpected output.
Any ideas about what I'm doing wrong, and what I could use to solve the problem?
local_to_utc actually expects a Time or a DateTime instance:
TZInfo::Timezone.get('US/Eastern').local_to_utc(DateTime.parse(date_src))
# => #<DateTime: 2014-07-08T03:10:00+00:00 ((2456847j,11400s,0n),+0s,2299161j)>
From the documentation, you can have a hint on what actually happened:
All methods in TZInfo that operate on a time can be used with either Time or DateTime instances or with nteger timestamps (i.e. as returned by Time#to_i). The type of the values returned will match the the type passed in.
What actually happens is the local_to_utc calls to_i on the input parameter, which on a string returns the parsed integer from the beginning of the string (2014 in your case since date is the string 2014-07-07T23:10:00+00:00), and adds the time difference to it - 18000 for "US/Eastern" (5 hour difference), and 0 for UTC:
date.to_i
# => 2014
TZInfo::Timezone.get('US/Eastern').local_to_utc(date) - date.to_i
# => 18000
TZInfo::Timezone.get('UTC').local_to_utc(date) - date.to_i
# => 0
So the bottom line is - kind of serendipitously you saw this weird behavior, which stems from the compilation of some surprising quirks of the APIs you used...

Resources