TimezoneIANA attempts to determine the local timezone in IANA format. If the TZ environment variable is set, this is used. Otherwise, /etc/localtime is used to determine the timezone. Reference: https://stackoverflow.com/a/63805394 On Windows platforms, instead of reading /etc/localtime, powershell
()
| 22 | // is used instead to get the current time location in IANA format. |
| 23 | // Reference: https://superuser.com/a/1584968 |
| 24 | func TimezoneIANA() (*time.Location, error) { |
| 25 | loc, err := locationFromEnv() |
| 26 | if err == nil { |
| 27 | return loc, nil |
| 28 | } |
| 29 | if !xerrors.Is(err, errNoEnvSet) { |
| 30 | return nil, xerrors.Errorf("lookup timezone from env: %w", err) |
| 31 | } |
| 32 | |
| 33 | // https://superuser.com/a/1584968 |
| 34 | cmd := exec.Command("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive") |
| 35 | // Powershell echoes its stdin so write a newline |
| 36 | cmd.Stdin = strings.NewReader(cmdTimezone + "\n") |
| 37 | |
| 38 | outBytes, err := cmd.CombinedOutput() |
| 39 | if err != nil { |
| 40 | return nil, xerrors.Errorf("execute powershell command %q: %w", cmdTimezone, err) |
| 41 | } |
| 42 | |
| 43 | outLines := strings.Split(string(outBytes), "\n") |
| 44 | if len(outLines) < 2 { |
| 45 | return nil, xerrors.Errorf("unexpected output from powershell command %q: %q", cmdTimezone, outLines) |
| 46 | } |
| 47 | // What we want is the second line of output |
| 48 | locStr := strings.TrimSpace(outLines[1]) |
| 49 | loc, err = time.LoadLocation(locStr) |
| 50 | if err != nil { |
| 51 | return nil, xerrors.Errorf("invalid location %q from powershell: %w", locStr, err) |
| 52 | } |
| 53 | |
| 54 | return loc, nil |
| 55 | } |