How to get time in seconds with add time zone in go - go

I am using time.Time in go. to get time in seconds (the number of seconds elapsed since 1970's January 1) I am using
now := Time.now()
loc, err := time.LoadLocation(country.Timezone) // time zone in Asia/Dhaka
now = now.In(loc)
then,
seconds := now.Unix()
but the seconds giving seconds without adding the time zone seconds. it actually giving the seconds in UTC. My question is, how can I get seconds with added 6 hours ( asia/dhaka time zone is UTC+6)?

If you want current clock time's second part only use below code:
loc := time.FixedZone("some_common_name", 6*60*60)
ts := time.Now().In(loc).Second()
fmt.Println(ts)
If you want seconds from start of current year(like 01.01.1970)
loc := time.FixedZone("some_common_name", 6*60*60)
tp := time.Date(1970, 1, 1, 0, 0, 0, 0, loc)
ts := time.Now().Sub(tp).Seconds()
fmt.Printf("%v", ts)
In case, you want different time zone information, change offset value of time.FixedZone() functions. As, if you want GMT +5, then use 5*60*60 as offset value

I've read a number of posts and most of them are rightfully biased that Unix() time should be exactly that; meaning UTC. However, In my particular case others, like the TCL team, are a little loose. Both input and output allow the user to override the TZ. Furthermore the default TZ has it's own rules.
In my case I was not even using times... only dates. However, the closer to the date boundary the more likely it change days and thus bang up the date expressions etc.
In TCL there is UTC seconds from 1/1/1970 but there is also TZ adjusted seconds from 1/1/1970. (right or wrong I need some compatibility)
// parse the time string (the value does not have the TZ)
t, _ := time.Parse(format, value)
// set the location.
t = t.In(location)
// get the offset seconds from TZ
_, offset := t.Zone()
// adjust the Unix() seconds by the offset.
retval = fmt.Sprintf("%d", t.Unix()-int64(offset))
I'm in EST5EDT and it works here when location is EST5EDT and Local. I did not try anything on the other side of the UTC.
UPDATE: Well... Someone once said show me a programmer who knows dates and times and I'll show you someone who doesn't. The code above worked just fine as Local and UTC were on the same calendar day. But as soon as UTC moved into the next calendar day the Seconds were exactly 24hrs apart. I can squeeze the last second out of this so that TCL and my app work similarly but I'm better off doing this in the app code rather than in the libs.

Related

Is there an easy way to change the hour of an existing time?

So far the best that I have is this, which is long and it's easy to make a mistake:
cst, _ := time.LoadLocation("Asia/Shanghai")
orig := time.Now().In(cst)
new := time.Date(orig.Year(), orig.Month(), orig.Day(), 13, orig.Minute(), orig.Second(), orig.Nanosecond(), cst)
fmt.Printf("%v", new)
https://play.golang.org/p/dv_7rltueY6
It may seem easier to do arithmetic with durations.
// NO!
// const newHour = 13
// d := orig.Add(time.Duration(newHour - orig.Hour()) * time.Hour)
However, this won't work during daylight savings. Your original code is about as correct as it can be... the time.Date() function will account for daylight savings, although there are certain edge cases with no good answer (what happens when you set the time to 1:30AM when the clocks go forward in North American eastern time?)

Why does `time.Since(start).Seconds()` always return 0?

I am on the first chapter The Go Programming Language (Addison-Wesley Professional Computing Series) and the 3rd exercise in the book asks me to measure code performance using time.
So, I came up with the following code.
start := time.Now()
var s, sep string
for i := 1; i < len(os.Args); i++ {
s += sep + os.Args[i]
sep = " "
}
fmt.Print(s)
fmt.Printf("\nTook %.2fs \n", time.Since(start).Seconds())
fmt.Println("------------------------------------------------")
start2 := time.Now()
fmt.Print(strings.Join(os.Args[1:], " "))
fmt.Printf("\nTook %.2fs", time.Since(start2).Seconds())
When I ran this code on Windows and Mac, it always return 0.00 second. I added a pause in my code to check whether it's correct and it seems fine. What I don't understand is why it always returns 0.0.
There is very little code between your start times and the time.Since() calls, in the first example just a few string concatenations and an fmt.Print() call, in the second example just a single fmt.Print() call. These are executed by your computer very fast.
So fast, that the result is most likely less than a millisecond. And you print the elapsed time using the %.2f verb, which rounds the seconds to 2 fraction digits. Which means if the elapsed time is less than 0.005 sec, it will be rounded to 0. This is why you see 0.00s printed.
If you change the format to %0.12f, you will see something like:
Took 0.000027348000s
Took 0.000003772000s
Also note that the time.Duration value returned by time.Since() implements fmt.Stringer, and it "formats" itself intelligently to a unit that is more meaningful. So you may print it as-is.
For example if you print it like this:
fmt.Println("Took", time.Since(start))
fmt.Println("Took", time.Since(start2))
You will see an output something like this:
Took 18.608µs
Took 2.873µs
Also note that if you want to measure the performance of some code, you should use Go's built-in testing and benchmarking facilities, namely the testing package. For details, see Order of the code and performance.

how to convert duration to days in Go

In Go, how can I convert duration to number of days?
for eg 1W => 7days, 1Y => 365days etc.
The short answer, for many common purposes, is just to divide the number of hours by 24, to get a generally useful approximation of the number of days.
d, _ := time.ParseDuration("48h")
days := d.Hours()/24 // 2 days
However, this isn't always "correct", depending on your situation. Consider:
How many days between November 1, 2018 midnight and November 8, 2018 midnight? The answer actually depends on at least two things: Your definition of day, and where you're located. If you calculate the duration between the two dates, and divide as described above, your answer will be 7.04167 days, if you're located in the US, due to the daylight savings change.
If your time period happens at the right time in the spring, your answer might be 6.95833 days, due to the DST change in the other direction.
If you account for multiple timezones, leap seconds, or other aberation from "normal", you can end up with even more confusing results.
For some purposes, 7.04167 days would be the right answer. For other purposes, 7 would be the right answer.
So the first task, when trying to calculate "days" is always to determine what definition matters to you. Then second, figure out how to calculate a meaningful number that satisfies that need.
you can try this pkg: https://github.com/hako/durafmt
package main
import (
"fmt"
"github.com/hako/durafmt"
)
func main() {
duration, err := durafmt.ParseString("354h22m3.24s")
if err != nil {
fmt.Println(err)
}
fmt.Println(duration) // 2 weeks 18 hours 22 minutes 3 seconds
// duration.String() // String representation. "2 weeks 18 hours 22 minutes 3 seconds"
}

Is return value of GetTimeZoneInformation also valid for dynamic DST zones?

Following function which I have written in Delphi (however, my question is not specific to Delphi) does output the current UTC unix timestamp:
function CurrentUnixTimeUTC: int64;
var
tzi: TTimeZoneInformation;
begin
// Get the current unix timestamp in local time.
Result := DateTimeToUnix(Now);
// First, add the DST specific bias
case GetTimeZoneInformation(tzi) of
TIME_ZONE_ID_INVALID:
RaiseLastOSError;
TIME_ZONE_ID_UNKNOWN:
; // Unknown what to do. We simply don't apply any bias.
TIME_ZONE_ID_STANDARD:
Result := Result + tzi.StandardBias * 60;
TIME_ZONE_ID_DAYLIGHT:
Result := Result + tzi.DaylightBias * 60;
end;
// Now apply the region specific bias
Result := Result + tzi.Bias * 60;
end;
The function works and has the same output in Germany as in California.
While researching MSDN, I have additionally found the function GetDynamicTimeZoneInformation .
From reading the MSDN (which has an incomplete definition of the member "Bias" btw), it is not clear to me if simply calling GetTimeZoneInformation is sufficient to have my function CurrentUnixTimeUTC also work in regions which have dynamic DST settings (i.e. the DST dates change from year to year). In other words, can GetTimeZoneInformation sucessfully tell if the system is currently in DST mode or not, or do I need to call GetDynamicTimeZoneInformation instead, if I want to be compatible with computers which are in a time zone where dynamic DST rules are applied?
If you're just looking to get the current UTC time from the Win32 API, you shouldn't involve time zones. The OS will handle that automatically. It's faster to simply get the UTC time directly using GetSystemTime, or GetSystemTimeAsFileTime.
For example, in .NET, DateTime.UtcNow just makes a call to GetSystemTimeAsFileTime. But DateTime.Now first calls DateTime.UtcNow and then gets the local time zone and applies it to that time.
Regarding the dynamic DST info that you originally asked about, I believe that it would be sufficient to call GetTimeZoneInformation, because Windows should be copying the dynamic DST rule that applies to the current date and time into the non-dynamic values in the registry. But like I said, it's better to just get the UTC time directly.
I'm surprised there is no Delphi function for getting the UTC time directly. It must be an artifact of the ages, since many things were done locally in the time when Delphi was widely used.
A few Delphi functions:
function NowUTC: TDateTime;
var
st: TSystemTime;
begin
GetSystemTime(st);
result := EncodeDateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
end;
function CurrentUnixUTCTimestamp: int64;
begin
result := DateTimeToUnix(NowUTC);
end;

Simple Add to time and compare GO

Hi I can't seem to get my head around the correct way to do time arithmetic in Go.
I have a time "object" later initialized to Now() and stored.
insertTime time.Time
Later, I need to see if the item is older than 15 minutes.
How do i do this?
Do I need to create a Duration of 15 Minutes add it to the current time and compare? If so, how do I do that?
func (Time) After will be helpful, I believe. Schema:
when := time.Now()
...
if time.Now().After(when.Add(15*time.Minute)) {
// Conditionally process something if at least 15 minutes elapsed
}
Instead of a variable, when could be a field of some struct, for example.
Alternative approach:
deadline := time.Now().Add(15*time.Minute)
...
if time.Now().After(deadline) {
// Conditionally process something if at least 15 minutes elapsed
}
I prefer the later version personally.

Resources