Understanding tz offset discrepancy on different systems - go

Hoping someone can see what I'm doing wrong, or misunderstanding.
I was using the time pkg in the Go Sandbox, to become familiar with how to use the timezone specific functions correctly.
Even though I already knew some of the offsets, I used the following site to double check myself : https://documentation.mersive.com/content/topics/api-timezones.htm.
In this case, when I ask for the offset for "America/New_York", I expect -14400.
However, when I ran the following on the Go Sandbox, I get -18000 instead:
https://play.golang.org/p/aU0JFHzueU1
americatz, err := time.LoadLocation("America/New_York")
if err != nil {
fmt.Println(err)
return
}
t := time.Now().In(americatz)
zone, offset := t.Zone()
fmt.Printf("%v :: %v\n", zone, offset)
I noticed that when I brought the same code over to a linux machine, it did exactly what I expected. I'm nervous, because I don't have a firm understanding why the two output's for a very common tz would be different.
I know enough that LoadLocation looks for a zipfile from the ZONEINFO env var. Otherwise it'll look in other system places like the $GOROOT/lib/time/zoneinfo.zip.
Is it really just plain and simple that the Go Server the code runs on vs the linux server have different zone info files? And if I want the exact same behavior across all systems... does this mean I need to always load in and set my own ZONEINFO variable? I feel like most people would expect -14400...
Thanks.

In the playground the time is set to "2009-11-10 23:00:00 UTC" because "This makes it easier to cache programs by giving them deterministic output." (from the 'About' box).
This can have an impact on the timezone offset due to daylight savings. The following will give the answer you are expecting:
today := time.Date(2020,10,16,0,0,0,0,americatz)
zone, offset = today.Zone()
fmt.Printf("%v :: %v\n", zone, offset)
Playground
Further detail:
Due to daylight savings the offset changes depending upon the time; for example:
time.Date(2020,10,16,0,0,0,0,americatz).Zone() will return an offest of -14400 whereas time.Date(2020,1,16,0,0,0,0,americatz).Zone() would return -18000.
It just so happens that the time that now() returns in the playground (2009-11-10) is EST (daylight savings ended Sunday, 1 November 2009, 2:00 a.m.) rather than EDT. If you run your test again in a month you will not see this difference because both times will be in EST.

Related

Get complete UTC offset format

I need to get the UTC offset for a location. I am getting trouble with the inconsistency of the results from different values. All I need to get are values in the format +HHMM (e.g., +0100 for "Europe/Rome").
func main() {
loc, _:= time.LoadLocation("Asia/Kathmandu")
offset, others:= time.Now().In(loc).Zone()
fmt.Println(offset, others)
}
Playground
What I get:
"Asia/Kathmandu": +0545 (suitable)
"Asia/Ho_Chi_Minh": +07 (should be +0700)
"America/Phoenix": MST (should be -0700)
"Europe/Rome": CET (should be +0100)
Reference Timezone country names
The Zone() method you're using is working exactly as advertized.
Zone computes the time zone in effect at time t, returning the abbreviated name of the zone (such as "CET") and its offset in seconds east of UTC.
A better approach for you would be to use the Format method. Something like:
zone := time.Now().In(loc).Format("-0700")
Of course, be aware: Even this won't be 100% consistent, due to daylight savings time.

Why running Golang's time.Now() at OpenWRT always get UTC time?

I wrote a Golang program that runs on OpenWRT.
package main
import (
"fmt"
"time"
)
func main(){
fmt.Println(time.Now())
}
When I run this program on my Macbook, I always get the correct local time.
However, when running this program on OpenWRT, I always get UTC time.
I have set the time zone and time of OpenWRT. When I execute uci show system, I can see the right time zone. When I execute date the right local time can be display correctly.
So my question is, how do I get the correct local time using Golang's time.Now() on OpenWRT?
The root of my problem is that my OpenWRT lacks the zoneinfo package. So I run opkg update && opkg install zoneinfo-xxx first.
This is part of go/src/time/zoneinfo_unix.go:
func initLocal() {
// consult $TZ to find the time zone to use.
// no $TZ means use the system default /etc/localtime.
// $TZ="" means use UTC.
// $TZ="foo" means use /usr/share/zoneinfo/foo.
...
}
According to this file, if there is no "TZ" variable, Golang will use the time zone pointed to by /etc/localtime when calling time.Now().
Then I set time zone at /etc/config/system (option zonename 'xxxxxx') and run /etc/init.d/system restart. Finally, I can get the correct time.Now().
OpenWRT stores the time zone inside a file named /etc/TZ. If this file is missing or empty, OpenWRT assumes the local time equals UTC time. Source
how do I get the correct local time using Golang's time.Now() on
OpenWRT?
Specifying the Time Zone with TZ
The is the value you must add to or substract from the local time to get the UTC time. This offset will be positive if the local time zone is west of the Prime Meridian and negative if it is east.

Why is my Go server memory leaking? [duplicate]

This question already has answers here:
Cannot free memory once occupied by bytes.Buffer
(2 answers)
Closed 4 years ago.
I've written a simple TCP server.
The problem is that when stress-testing it, it seems that the memory usage is increasing dramatically, and not decreasing when he test is done.
When the server is started, it takes ~700KB.
During and after the stress-test, the memory usage jumps to ~7MB.
Here's my code:
package main
import (
"net"
"log"
"fmt"
"bufio"
)
func main() {
ln, err := net.Listen("tcp", ":8888")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handle(conn)
}
}
func handle(conn net.Conn) {
defer conn.Close()
fmt.Println("Accepted", conn.LocalAddr())
for {
buf, err := bufio.NewReader(conn).ReadString('\n')
if err != nil {
break
}
msg := string(buf[:len(buf)-2])
fmt.Println("Received", msg)
conn.Write([]byte("OK\n"))
}
}
Any help is much appreciated.
Note: I'm using tcpkali for loading it. This is the command line:
tcpkali -em "testing\r\n" -c 100 -r 1000 -T 60 127.0.0.1:8888
EDIT: Following some comments below, I ran some tests and here are the results:
Started the server and ran tcpkali.
After the first run, RSS was at 8516.
After a second run, RSS climbed to 8572.
Server is now idle. 5 minutes later, RSS climbed to 8588.
5 more minutes later, RSS climbed to 8608, and seems stable.
After 15 minutes of break, I ran tcpkali again, and RSS climbed to 8684.
A few minutes break, another tcpkali run, RSS climbs to 8696.
A few minutes break, another tcpkali run, RSS climbs to 8704.
A few minutes break, another tcpkali run, RSS climbs to 8712.
Now, I don't know what you call this, but I call this a memory leak. Something is wrong here. No memory is freed, and RSS is keep climbing every time I run a test. Obviously, this thing cannot be deployed to production as it will eventually consume all available memory.
I also tried calling os.FreeOSMemory() but nothing happens.
My system is Go 1.9.4 on macOS 10.13.1. Is this environment related or am I missing something?
LAST UPDATE:
Following #Steffen Ullrich answer and the tests that failed on my environment, I gave it a try on Ubuntu server, and the memory is freed after a few minutes of idle time.
Seems like there's an issue with macOS.
Go does not release memory it allocated from the OS immediately. The reason is probably that allocating memory is costly (needs system calls) and the chance is high that it will be needed in the near future anyway again. But, if memory gets long enough unused it will be released eventually so that the RSS of the process decreases again.
Doing your test again with slight modifications will show this (it did at least for me):
Start you program and look at the RSS.
Run tcpkali, wait for tcpkali to end and look at the RSS again. It is much higher now since lots of memory was needed for the program to do the intended task.
Don't stop the program but run tcpkali again and wait again for it to end. When looking at the RSS you should see that it did not grow (much) further. This means that the program used the already allocated memory again and did not need to allocate new memory from the system.
Now monitor the RSS and wait. After a while (about 10 minutes on my system) you should see the RSS go down again. This is because the program has determined now that the allocated but unused memory will probably not be used any longer and returned the memory back to the OS.
Note that not all memory might be given back. According to Understanding Go Lang Memory Usage it will not return (in go 1.3) the memory used for the stacks of the go routines since it is more likely that this will be needed in the future.
For testing you might also add some debug.FreeOSMemory() (from runtime/debug) at strategic places (like when you break out of the loop in the goroutine) so that the memory gets returned earlier to the OS. But given that the lazy return of memory is for performance such explicit freeing might impact the performance.

How to convert between timezones in Go? [duplicate]

This question already has answers here:
Convert UTC to "local" time in Go
(3 answers)
Closed 7 years ago.
For example time.Now() has a timezone of UTC.
utcNow := time.Now()
fmt.Println(utcNow)
Outputs
2009-11-10 23:00:00 +0000 UTC
How do I convert this time to Japan Standard time?
It looks like you're running that in the Go playground, which is why the time is automatically set to UTC (it's also always set to November 2009 when a program is launched).
If you run time.Now() on your own machine, it should pick up the local region. Alternatively, if you want to force the time to be in a specific timezone, you can use a time.Location object along with the time.Time.In function.
l, err := time.LoadLocation("Asia/Tokyo") // Look up a location by it's IANA name.
if err != nil {
panic(err) // You can handle this gracefully.
}
fmt.Println(utcNow.In(l))
Note that it's still showing the same moment in time, but now with JST's offset.
For more information, look at the go documentation for the time package. http://golang.org/pkg/time

a simple real-time-clock driver program not getting output

I wrote a driver program which will interact with RTC and gives the time.
program is:
outb(GET_HR, CMD_REG);
hrs = inb(STAT_REG);
outb(GET_MIN, CMD_REG);
min = inb(STAT_REG);
pr_info("time: hrs:min\n", hrs, min);
Its working, but giving in format of GMT. I want my local time(GMT+5.30). I explicitly added 5:30 in the program. some times its not giving correct time. Is there any implicit function to get local time?
it is not task of the kernel to do time conversions. You should always work with UTC times in kernel and translate them in userspace to localtime.

Resources