Date Format shows wrong date - go

I'm trying to format a date like this: [daynumber] [monthname] [fullyear]
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.Format("1 January 2014"))
}
However this prints out "11 November 10110" instead of the correct date "29 November 2014".
What is the correct way to use Time.Format?

Try:
fmt.Println(t.Format("2 January 2006"))
From Time.Format()
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time,
Mon Jan 2 15:04:05 -0700 MST 2006
The article "Parsing and formatting date/time in Go " adds:
The use of a mnemonic over obscure formatting codes I think reflects the pragmatism of Go’s developers and their focus on creating a language that makes its users more productive
Ironically, I have trouble remembering the exact values and order of that format template.
(Especially the day and month that I keep mixing up, being used to the dd-mm convention, as opposed to mm-dd).

Related

in Power Automate, how can I convert long-format datetime strings?

In a Power Automate / MSFlow flow, I receive a string like this:
Saturday, July 31, 2021 1:35 AM  |  (UTC+01:00) Dublin, Edinburgh, Lisbon, London
I need to convert it to the format Sharepoint expects, i.e. a ISO 8601 for UTC:
YYYY-MM-DDTHH:MM:SS
I painfully built a flow that does most of the work; however, at the thought of having to manually manage the timezone offset my heart finally gave out. It's shocking that in 2021 a product like this cannot parse a datetime like we could do in any language in 1995.
So my question is: what's the easiest way to parse this datetime correctly in PA/Flow...?
I followed the MS reference:
Workflow definition language functions reference: formatDateTime
And the way to go was with "formatDateTime" function:
formatDateTime('<timestamp>', '<format>'?)
But, before that, the timestamp should be reformated in your case.
My approach will be the following:
Let's assume that the input string will be stored in a variable named timestamp_original.
Take the part before "|" character from the timestamp_original. and remove the Day (at the beginning) from the result.
pass the result to the formatDateTime function.
Use the convertTimeZone function to achieve the TimeZone conversion. (but this part is not working as I expected).
So the final result should be obtained by using the next expressions:
convertTimeZone(formatDateTime(first( split( substring(variables('timestamp_original'), add(2, indexOf(variables('timestamp_original'),','))) , '|' ) )), 'Central Europe Standard Time', 'Greenwich Standard Time')
The solution to the point 3, should be extracting the TimeZone from the timestamp_original string:
trim(first(split(last( split(variables('timestamp_original'), '(' ) ), ')')))
And add some logic to test if this TimeZone contains "UTC+" or "UTC-" and add or extract hours from the obtained timestamp.
I think you can do this.
It should be noted that the variable 'timestamp_original' should be initially in the next format (as the OP mentionned):
Saturday, July 31, 2021 1:35 AM | (UTC+01:00) Dublin, Edinburgh, Lisbon, London
So the result will be: (using the convertTimeZone function)
2021-07-30T23:35:00.0000000
And without using the convertTimeZone function:
2021-07-31T01:35:00.0000000
I hope this has helped. Good luck.

Go time.Time String() adds "+0000 +0000", why?

I'm retrieving time from a Postgres DB.
Let's say it is:
2020-02-27 08:57:36.774147+00
Now I wanna write it in output like a string and I do it like this:
var myTime time.Time
fmt.Println(myTime.String())
In output it writes something different:
2020-02-27 08:57:36.774147 +0000 +0000
I need that value to be the same because I need to query something else with it.
Maybe the same issue is described here: https://github.com/golang/go/issues/11712
The function you need is time.Format. Replace "myTime.String()" with "myTime.Format(layout)" with a desired layout as the argument (e.g. the predefined "time.RFC3339" or a reference time format "2006-01-02 15:04:05.000000-07").
go doc:
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted
according to layout, which defines the format by showing how the reference
time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the
desired output. The same display rules will then be applied to the time
value.
A fractional second is represented by adding a period and zeros to the end
of the seconds section of layout string, as in "15:04:05.000" to format a
time stamp with millisecond precision.
Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and
convenient representations of the reference time. For more information about
the formats and the definition of the reference time, see the documentation
for ANSIC and the other constants defined by this package.

Parsing a string into a ZonedDateTime with a DateTimeFormatter

I'm trying to parse this String into a ZonedDateTime:
"Mon 14 Aug 2017 02:00 AM CEST"
Here my last try:
System.out.println("Test ZonedDateTime: " + ZonedDateTime.parse(
"Mon 14 Aug 2017 02:00 AM CEST",
DateTimeFormatter.ofPattern("EEEE dd M yyyy KK:mm a z")));
And the response:
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon 14 Aug 2017 02:00 AM CEST' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at be.hypertux.test.localtime.Main.main(Main.java:17)
Any ideas?
One problem is that short timezone names like CEST and CET are ambiguous and not standard. The ideal is to use IANA timezones names (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin).
I'm assuming that CEST is the Central Europe Summer Time, which is used by lots of different countries (that's why it's ambiguous: you can't know which country or region it is, because it's a too broad range).
Although most abbreviations are not recognized (due to its ambiguity), some "defaults" are assumed for retro-compatibility reasons. In the version I'm using (JDK 1.8.0_131), it defaults to Europe/Paris, but not sure if that's what you need. And it's not guaranteed to work for all abbreviations. In this case, you can define a preferred timezone to be used (and that will an arbitrary choice, but there's no other way since CEST is ambiguous).
Another problem is that the month and day of week are in English (Aug and Mon), and you didn't specify a java.util.Locale. In this case, the DateTimeFormatter takes the system's default locale (and it's probably not English - check the value of Locale.getDefault()). Anyway, the default locale can be changed without notice, even at runtime, so it's better to specify one when you're dealing with localized data (like month and day of week names).
So, you must specify a locale and define an arbitrary timezone as the preferred one to be used when an ambiguous name like CEST is found. For that, you can use a java.time.format.DateTimeFormatterBuilder, a set of preferred timezones and a java.time.format.TextStyle:
// create set of preferred timezones
Set<ZoneId> zones = new HashSet<>();
// my arbitrary choice for CEST
zones.add(ZoneId.of("Europe/Brussels"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// date and time
.appendPattern("EEE dd MMM yyyy hh:mm a ")
// timezone short name with custom set of preferred zones
.appendZoneText(TextStyle.SHORT, zones)
// create formatter (use English locale for month and day of week)
.toFormatter(Locale.ENGLISH);
String input = "Mon 14 Aug 2017 02:00 AM CEST";
System.out.println(ZonedDateTime.parse(input, formatter));
The output will be:
2017-08-14T02:00+02:00[Europe/Brussels]
Note that I used Europe/Brussels as the preferred timezone. You can check all the available zone names (and choose accordingly) with ZoneId.getAvailableZoneIds().
I'm using hh for the hours, which is the hour-clock-of-am-pm field (values from 1 to 12). But in your code you used KK, which is the hour-of-am-pm field (values from 0 to 11). Check which one is best for your case.
A timezone is the set of all different offsets that a region had, has and will have during its history, and the dates when Daylight Saving Time starts and ends, etc. If 2 regions had some difference in this history, they'll have different timezones (even though they use the same rules today).
Just because Paris and Brussels use the same rules today (CET and CEST), it doesn't mean it'll be like this forever (because timezones rules are defined by governments and laws and there's no guarantee that they won't be changed at any time in the future).
That's why you must define some specific timezone instead of relying on ambiguous short names (even though their use is common and widespread).
In order for your format string to work, your date would need to be formatted like so: Monday 14 8 2017 02:00 AM CEST
Take out an E and add a couple of Ms and that should do it.

Unix timestamp format conversion

A unix_timestamp of 1405936049 corresponds to: 2014-07-21 09:47:29. My goal is to derive the latter form from the timestamp.
After reading the format documentation, I came up with the following:
fmt.Println(time.Unix(1405936049, 0).Format("2006-01-02 15:04:05"))
which yields: 2014-07-21 02:47:29, which makes sense, since time.Unix(1405936049, 0) gives: 2014-07-21 02:47:29 -0700 PDT (to be clear, I want: 2014-07-21 09:47:29, the hour is incorrect).
I'm sure if I knew the correct terminology, I'd be able to find a solution in the documentation, but at this point, I'm uncertain how to tell the parser to account for -0700 or perhaps an alternative solution would be to use something besides time.Unix(), so that the resulting time would have already accounted for the hour difference? Any help would be appreciated.
You want the UTC time, not your local PDT time. For example,
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Unix(1405936049, 0).UTC().Format("2006-01-02 15:04:05"))
}
Output:
2014-07-21 09:47:29
You have to use Location for this:
loc, _ := time.LoadLocation("Europe/Paris")
fmt.Println(time.Unix(1405936049, 0).In(loc).Format("2006-01-02 15:04:05"))
I think the location you want is "UTC", but I let you check (otherwise, here is a list of all available locations). The reason why in playground the format is already 09:47:29 is that playground does not include locations and uses UTC by default.

Is there a full implementation for ISO-8601 date parsing for Ruby?

The Time.iso8601 method is a restricted subset of ISO-8601.
What are its limitations?
Does anyone know of a full implementation for Ruby? I'm using MRI 1.8.7.
Update
It looks like there isn't a single class that handles all of the various 8601 date and date/time combinations. However, I have managed to work around the problems by using both the Date.parse and Time.iso8601 methods. The downside is that you need to decide in code whether the input looks like a date or a date/time.
Warning : Timezone differences
Time.iso8601 and Time.parse behave differently.
>> Time.parse("2010-09-06T12:27:00.10-05:00")
=> Mon Sep 06 18:27:00 +0100 2010
>> Time.iso8601("2010-09-06T12:27:00.10-05:00")
=> Mon Sep 06 17:27:00 UTC 2010
Differences between Time.iso8601 and ISO-8601
This document touches on the differences between what is in ISO-8601 and what is supported by Ruby. The short answer is that the number of possible formats is restricted.
Yes, but unfortunately it's in Ruby 1.9.
require "date"
Date.iso8601("2010-W32-5").strftime
#=> "2010-08-13"
I don't believe there are any implementations for Ruby 1.8.7 (or at least I couldn't find any). You could either try to upgrade to Ruby 1.9, which is pretty stable as of 1.9.2. Alternatively, you could try to parse the dates yourself.
To convert an ISO8601 date into the local time zone, do this:
require "time"
dt1 = Time.parse("2010-09-06T12:27:00.10-05:00")
To convert an ISO8601 date into UTC, do this:
dt2 = Time.iso8601("2010-09-06T12:27:00.10-05:00")
If you compare the dates returned by the above queries, they will be identical (i.e. dt1 === dt2). However, accessing date components (like year, month, day, hour, etc.) will return values appropriate for the time zone (either UTC or local). The same applies to strftime.

Resources