carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package main
2
3import (
4 "os"
5 "regexp"
6 "strings"
7)
8
9// tzName is the shape of an IANA zone name the console will accept (spec
10// §6.2 step 1). Anything else is not sent: the console then falls back to
11// the request's IP, then the home.
12var tzName = regexp.MustCompile(`^[A-Za-z0-9_+\-]+(/[A-Za-z0-9_+\-]+){0,2}$`)
13
14var notAZone = map[string]bool{"localtime": true, "posixrules": true, "Local": true}
15
16// localTimezone finds this machine's IANA zone name, portably (no build
17// tags; the 20-cross gate builds it for darwin, windows and linux-arm64):
18// $TZ, else the /etc/localtime symlink target, else /etc/timezone, else "".
19// Windows has none of these, so only a valid $TZ is ever sent there.
20func localTimezone(getenv func(string) string, readlink func(string) (string, error), readFile func(string) ([]byte, error)) string {
21 if tz := clean(strings.TrimPrefix(strings.TrimSpace(getenv("TZ")), ":")); tz != "" {
22 return tz
23 }
24 if target, err := readlink("/etc/localtime"); err == nil {
25 if tz := clean(target); tz != "" {
26 return tz
27 }
28 }
29 if b, err := readFile("/etc/timezone"); err == nil {
30 line, _, _ := strings.Cut(string(b), "\n")
31 return clean(line)
32 }
33 return ""
34}
35
36func clean(s string) string {
37 s = strings.TrimSpace(s)
38 if _, after, ok := strings.Cut(s, "zoneinfo/"); ok {
39 s = after
40 }
41 if s == "" || strings.HasPrefix(s, "/") || notAZone[s] || len(s) > 64 || !tzName.MatchString(s) {
42 return ""
43 }
44 return s
45}
46
47func detectTimezone() string { return localTimezone(os.Getenv, os.Readlink, os.ReadFile) }
48