New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time: LoadLocation doesn't work on windows if Go is not installed #21881

Open
iman75 opened this Issue Sep 14, 2017 · 16 comments

Comments

Projects
None yet
9 participants
@iman75

iman75 commented Sep 14, 2017

What version of Go are you using (go version)?

go version go1.8.3 windows/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Users\Iman Akabi\go
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
set PKG_CONFIG=pkg-config
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2

What did you do?

https://play.golang.org/p/VuJ3ofkdk8
package main

import (
"fmt"
"time"
"log"
)

func main() {
var ParisLocation, err = time.LoadLocation("Europe/Paris")
if(err != nil) {
log.Fatal(err)
}

fmt.Println(ParisLocation)

}

I built this basic go code and generated an executable file.
I have an error when I run this executable on a windows machine without Go installed because time.LoadLocation needs to aceess to "zoneinfo.zip" located at $GOROOT/lib/time/zoneinfo.zip.

What did you expect to see?

Europe/Paris

What did you see instead?

open c:\go\lib\time\zoneinfo.zip: The system cannot find the file specified.

@ianlancetaylor ianlancetaylor changed the title from time.LoadLocation doesn't work on windows if go is not installed to time: LoadLocation doesn't work on windows if go is not installed Sep 14, 2017

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Sep 14, 2017

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 14, 2017

I don't see how we can fix this, at least not without bloating the size of almost every Go binary on Windows. I'm open to suggestions.

@skirmish

This comment has been minimized.

skirmish commented Sep 14, 2017

On windows couldn't it (default to|try) the (current working directory|executable location) to load the zoneinfo.zip? That way you only can include the file when it is required. Yeah, it's an extra hoop to jump through for us windows users, but I guess it's not too big of an ordeal seeing as the executable has to be distributed somehow, one extra file might not be too bad...

@alexbrainman

This comment has been minimized.

Member

alexbrainman commented Sep 14, 2017

On windows couldn't it (default to|try) the (current working directory|executable location) to load the zoneinfo.zip?

Sounds simple enough for me.

Alex

@glycerine

This comment has been minimized.

glycerine commented Sep 21, 2017

zoneinfo.zip is a mere 366776 bytes, a small number amongst friends. I think of a typical go binary as a 10MB +/- 5MB affair, and I would happily increase that by 366KB (3% of the mean, but small compared to the standard deviation) to have my binaries be portable to windows.

@iman75 iman75 changed the title from time: LoadLocation doesn't work on windows if go is not installed to time: LoadLocation doesn't work on windows if Go is not installed Sep 22, 2017

@leighmcculloch

This comment has been minimized.

Contributor

leighmcculloch commented Nov 6, 2017

I don't see how we can fix this, at least not without bloating the size of almost every Go binary on Windows.

Providing the tzdata ourselves in the binary if a specific package is imported (e.g. time/zone) seems less worse to me than requiring every Windows user to install Go, which is much larger to download and is inconsistent with the static binary.

Could we duplicate the time.LoadLocation function to another package which also contains the tzdata, e.g. zone.LoadLocation. This new function would operate the same as time.LoadLocation, but would load from a tzdata file built into a new zone package. This would only introduce bloat to binaries that imported the zone package, and applications could choose to use time.LoadLocation or zone.LoadLocation. We could mark time.LoadLocation as deprecated, or at least mention in a comment on it about it's limitations and about the alternative. Having the basic time code and the zone code in separate packages would mean the bloat is only introduced if applications specifically need it.

This would probably also resolve issues #20629 and #20969.

@alexbrainman

This comment has been minimized.

Member

alexbrainman commented Nov 7, 2017

Just an idea. On windows we use a particular Windows registry key to determine our timezone, and then we use a map that maps that string into std / dst values that are ultimately used to look in the tzdata blob. The "registry key" to "std / dst" map is hard coded in "abbrs" map in time package. This map contains 133 values at this moment. I wonder if we could strip tzdata blob to leave only the data we actually use on windows. I don't have time to try and implement this now, perhaps others do.

Alex

@nathan-osman

This comment has been minimized.

nathan-osman commented Jan 20, 2018

It would be awesome if there was a function that we could call to pass the contents of zoneinfo.zip to the time package. That way, the caller is responsible for determining where they want to put zoneinfo.zip and they have the option of embedding its contents in the executable.

@bradfitz

This comment has been minimized.

Member

bradfitz commented Jan 20, 2018

@nathan-osman

This comment has been minimized.

nathan-osman commented Jan 20, 2018

@bradfitz excellent, thanks! That will work perfectly.

@shabbyrobe

This comment has been minimized.

shabbyrobe commented Mar 1, 2018

I was pretty astonished by this. I can trivially build and deploy binaries to Windows just like I can everywhere else, but as soon as I try to work with a timezone, my application blows up. Go's tooling lulls me into a false sense of ease upon which I grow to rely, but it's a false promise. I'd much rather a larger binary than an... ahem... time-bomb like this ticking away.

@glycerine

This comment has been minimized.

glycerine commented Mar 2, 2018

All, what's the best current workaround for this? I need to distribute a windows binary, that uses time, and I'd like it not to blow up on user's boxes.

import "time/zone" would be great, eventually. But what's the solution today?

Thank you!

@bradfitz

This comment has been minimized.

Member

bradfitz commented Mar 2, 2018

The solution is to ship the tzdata yourself (linked into your binary or elsewhere) and then call https://golang.org/pkg/time/#LoadLocationFromTZData.

Or set the %ZONEINFO% environment variable to point to your shipped zoneinfo.zip.

@glycerine

This comment has been minimized.

glycerine commented Mar 2, 2018

Thanks Brad.

For others, the data that is passed to LoadLocationFromTZData is a file extracted from inside zoneinfo.zip, such as the file America/New_York, not zoneinfo.zip itself.

@shabbyrobe

This comment has been minimized.

shabbyrobe commented Mar 2, 2018

This is the quickie solution I used yesterday to get moving again: https://gist.github.com/shabbyrobe/b9a7a56e25bd8e441b7b3fe39dbb04fa

It relies on something not unlike the now-infamous https://github.com/jteeuwen/go-bindata to generate a go file with that tzfiles map referenced in the gist, which contains the base64-encoded zoneinfo.zip file I grabbed from the GOROOT of another Windows machine that was allowed to have Go installed on it (not always an option).

The code was dashed out under the duress of extreme time pressure so it's not exactly nice (and comes with absolutely no warranty whatsoever) but hopefully it can help someone else get out of the same jam.

@leighmcculloch

This comment has been minimized.

Contributor

leighmcculloch commented Mar 3, 2018

I created 4d63.com/tz because I find it more convenient to import a package than manually including a file to ride alongside an executable. It embeds Go's zoneinfo.zip and exports tz.LoadLocation(name) to load locations from the embedded tzdata.

@glycerine

This comment has been minimized.

glycerine commented Mar 3, 2018

Awesome @leighmcculloch. That should really become part of the standard library (or rather just be the implementation of time.LoadLocation on Windows), but while waiting for that, its just great to have it available. In the meantime, all calls to time.LoadLocation, in order to not crash on windows/OS without zoneinfo, need to become calls to tz.LoadLocation() after
import "4d63.com/tz".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment