Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go の Timezone と Go 1.15 の tzdata 埋め込み
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Hiroaki Sano
July 21, 2020
Programming
3.1k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go の Timezone と Go 1.15 の tzdata 埋め込み
某所のLT
Hiroaki Sano
July 21, 2020
More Decks by Hiroaki Sano
See All by Hiroaki Sano
社内 AI エージェント Synapse と セマンティックレイヤーの育て方
hiroakis
3
2.2k
バンドルカードの クレジットカード決済システムの 泥臭い運用
hiroakis
10
8.9k
クレジットカードの通信プロトコル ISO8583 と戦う
hiroakis
31
14k
トレタのインフラ運用
hiroakis
8
5.2k
Other Decks in Programming
See All in Programming
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
810
dRuby over BLE
makicamel
2
390
act1-costs.pdf
sumedhbala
0
120
Oxcを導入して開発体験が向上した話
yug1224
4
340
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
200
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
980
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
370
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
180
Oxlintのカスタムルールの現況
syumai
6
1.2k
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
4
870
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
180
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
290
Featured
See All Featured
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
450
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
220
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Six Lessons from altMBA
skipperchong
29
4.3k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
250
Google's AI Overviews - The New Search
badams
0
1.1k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.6k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
450
Designing Experiences People Love
moore
143
24k
Transcript
Go ͷ Timezone ͱ Go 1.15 ͷ tzdata ຒΊࠐΈ Remote.go
#1 Jul 17, 2020 Kanmu, Inc. Hiroaki Sano
2 ࠤ༟ষ Backend Engineer at Kanmu, Inc. @hiroakis hiroakis (@la_luna_azul)
3 όϯυϧΧʔυͭͬͯ͘·͢
Go 1.15 1
Go 1.15 5 1 • 20208݄ʹϦϦʔε༧ఆ • ݱࡏ Go 1.15
Beta1 ͕ར༻Մೳ IUUQTUXJUUFSDPNHPMBOHTUBUVT
Go 1.15: Beta1 6 1 $ go get golang.org/dl/go1.15beta1 $
go1.15beta1 download $ go1.15beta1 version go version go1.15beta1 darwin/amd64
Go 1.15: DRAFT RELEASE NOTES 7 1 IUUQTUJQHPMBOHPSHEPDHP
Go ͷ Timezone 2
Go ͷ Timezone: Time ߏମͱ Now() 9 2 // Now
returns the current local time. func Now() Time { sec, nsec, mono := now() mono -= startNano sec += unixToInternal - minWall if uint64(sec)>>33 != 0 { return Time{uint64(nsec), sec + minWall, Local} } return Time{hasMonotonic | uint64(sec)<<nsecShift | uint64(nsec), mono, Local} } type Time struct { wall uint64 ext int64 loc *Location }
10 2 // Now returns the current local time. func
Now() Time { sec, nsec, mono := now() mono -= startNano sec += unixToInternal - minWall if uint64(sec)>>33 != 0 { return Time{uint64(nsec), sec + minWall, Local} } return Time{hasMonotonic | uint64(sec)<<nsecShift | uint64(nsec), mono, Local} } type Time struct { wall uint64 ext int64 loc *Location } Go ͷ Timezone: Time ߏମͱ Now()
Go ͷ Timezone: Location ߏମ 11 2 var Local *Location
= &localLoc var localLoc Location type Location struct { name string []zone []zone tx []zoneTrans cacheStart int64 cacheEnd []zoneint64 cacheZone *zone } var localOnce sync.Once func (l *Location) get() *Location { if l == nil { return &utcLoc } if l == &localLoc { localOnce.Do(initLocal) // <— initLocal zoneinfo_xxx.go Ͱ֤ڥ͝ͱʹఆٛ } return l }
Go ͷ Timezone: Linux ͷ initLocal 12 2 var zoneSources
= []string{ "/usr/share/zoneinfo/", "/usr/share/lib/zoneinfo/", "/usr/lib/locale/TZ/", runtime.GOROOT() + "/lib/time/zoneinfo.zip", } func initLocal() { tz, ok := syscall.Getenv("TZ") switch { case !ok: z, err := loadLocation("localtime", []string{"/etc/"}) if err == nil { localLoc = *z localLoc.name = "Local" return } case tz != "" && tz != "UTC": if z, err := loadLocation(tz, zoneSources); err == nil { localLoc = *z return } } localLoc.name = "UTC" } UJNF[POFJOGP@VOJYHP
Go ͷ Timezone: Windows ͷ initLocal 13 2 var zoneSources
= []string{ runtime.GOROOT() + "/lib/time/zoneinfo.zip", } func initLocal() { var i syscall.Timezoneinformation if _, err := syscall.GetTimeZoneInformation(&i); err != nil { localLoc.name = "UTC" return } initLocalFromTZI(&i) } UJNF[POFJOGP@XJOEPXTHP
Go ͷ Timezone: Local Time ͷܾఆ 14 2 • ϩʔΧϧλΠϜ֤ڥͷ࣮
(zoneinfo_xxx.go) ͰॳظԽ • func (l *Location) get() ͕ݺΕͨͱ͖ʹͦΕ͕ηοτ͞ΕΔ • l.get() ͍ͭݺΕ͍ͯΔͷ͔ʁ • ͍͔ͭ͘ͷॴͰݺΕ͍ͯΔɻtime.Time time.Location ͷ Stringer ΠϯλʔϑΣΠεͷ࣮ͳͲɻ • Linux ΛྫʹऔΔͱɺl.get() ͕ݺΕͨͱ͖ʹ TZ ڥมΛݩ ʹ /usr/share… ͳͲΛ୳͠ʹߦ͘ɻ
Timezoneͷมߋ 2
Timezone ͷมߋ 16 2 • ͍͔ͭ͘ͷखஈ • ϩʔΧϧλΠϜΛมߋ͢Δ • *Location
Λඞཁͳͱ͖ʹ࡞ͬͯར༻͢Δ
Timezone ͷมߋ: Local Time Λมߋ͢Δ 17 2 • Linux ͷ߹
TZ ڥมΛઃఆ͢Δ • ͨͩ͠ॳճͷΈ • sync.Once(initLocal) Ͱηοτ͞ΕΔͨΊ • ΞϓϦέʔγϣϯͷ࣮Ͱ var time.Local άϩʔόϧมʹ *Location Λೖͯ͠͠·͏
Timezone ͷมߋ: *Location Λඞཁͳͱ͖ʹ࡞ͬͯར༻͢Δ 18 2 • *Location ΛಘΔ͍͔ͭ͘ͷAPI •
func LoadLocation(name string) • func LoadLocationFromTZData(name string, data []byte) • func FixedZone(name string, offset int) • *Location ͷ͍ํ • In(loc) • time.Now().In(loc) • time.Date(xxxx).In(loc) • …
Timezone ͷมߋ: func LoadLocation 19 2 func LoadLocation(name string) (*Location,
error) { zoneinfoOnce.Do(func() { env, _ := syscall.Getenv("ZONEINFO") zoneinfo = &env }) var firstErr error if *zoneinfo != "" { if zoneData, err := loadTzinfoFromDirOrZip(*zoneinfo, name); err == nil { if z, err := LoadLocationFromTZData(name, zoneData); err == nil { return z, nil } firstErr = err } else if err != syscall.ENOENT { firstErr = err } } if z, err := loadLocation(name, zoneSources); err == nil { return z, nil } else if firstErr == nil { firstErr = err } return nil, firstErr }
20 2 • zoneSources Λ୳͠ʹ͍͘ • ࠷ॳʹݟ͔͕ͭͬͨͭద༻͞ΕΔ • ͳ͚ΕΤϥʔʹͳΔ //
time/zoneinfo_unix.go var zoneSources = []string{ "/usr/share/zoneinfo/", "/usr/share/lib/zoneinfo/", "/usr/lib/locale/TZ/", runtime.GOROOT() + "/lib/time/zoneinfo.zip", } // time/zoneinfo_windows.go var zoneSources = []string{ runtime.GOROOT() + "/lib/time/zoneinfo.zip", } Timezone ͷมߋ: func LoadLocation
Timezone ͷมߋ: ଞͷखஈ 21 2 • func LoadLocationFromTZData(name string, data
[]byte) • ࣗͰ tzdata ͷੜσʔλΛ༻ҙ͓͍ͯͯ͠ಡ·ͤΔ • func FixedZone(name string, offset int) • ϩʔΧϧλΠϜ͔Βͷ offset Λϋʔυίʔυ͢Δ
Timezoneͷ 3
23 3 • ڥґଘ • Linux tzdata ͕ଘࡏ͍ͯ͠Δ͔ Go
͕Πϯετʔϧ͞Ε͍ͯ Δඞཁ͕͋Δ • Windows Go ͕Πϯετʔϧ͞Ε͍ͯΔඞཁ͕͋Δ Timezoneͷ
24 3 • ΞϓϦέʔγϣϯઌʹ tzdata ΛΠϯετʔϧ͓ͯ͘͠ • ΞϓϦέʔγϣϯઌʹ Go Πϯετʔϧ͓ͯ͘͠
• ࣗͰ tzdata Λ༻ҙͯ͠ LoadLocationFromTZData ͰಡΉ • FixedZone(name string, offset int)Λ͏(ͨͩ͠αϚʔλΠϜ͕ ߟྀ͞Εͳ͍) Timezoneͷ: ղܾࡦ
Go 1.15 embedded tzdata package 4
Embedded tzdata package 26 4 IUUQTHJUIVCDPNHPMBOHHPJTTVFT
27 4 • Timezone ͷѻ͍ʹखஈ͕૿͑ͨ • ΞϓϦέʔγϣϯઌʹ tzdata ΛΠϯετʔϧ͓ͯ͘͠ •
ΞϓϦέʔγϣϯઌʹ Go Πϯετʔϧ͓ͯ͘͠ • ࣗͰ tzdata Λ༻ҙͯ͠ LoadLocationFromTZData ͰಡΉ • Go 1.15 ͷ tzdata ຒΊࠐΈ Embedded tzdata package
28 4 IUUQTHPSFWJFXHPPHMFTPVSDFDPNDHP TSDUJNF[POFJOGP@SFBEHP Embedded tzdata package
29 4 IUUQTHPSFWJFXHPPHMFTPVSDFDPNDHP TSDUJNFU[EBUB[JQEBUBHP Embedded tzdata package
30 package main import ( "fmt" "log" "time" ) func
main() { jst, err := time.LoadLocation("Asia/Tokyo") if err != nil { log.Fatal(err) } tm := time.Now().In(jst) fmt.Println(tm) } 4 Embedded tzdata package: σϞ
31 $ go build -o jst main.go $ ./jst 2020-07-11
16:42:00.588488 +0900 JST 4 Embedded tzdata package: σϞ
32 FROM alpine:latest WORKDIR /app COPY jst /app CMD ["/app/jst"]
4 Embedded tzdata package: σϞ
33 $ GOOS=linux go build -o jst main.go $ docker
build -t jst:latest . $ docker run --rm jst:latest 2020/07/11 07:45:07 unknown time zone Asia/Tokyo 4 Embedded tzdata package: σϞ
34 package main import ( "fmt" "log" "time" _ "time/tzdata"
) func main() { jst, err := time.LoadLocation("Asia/Tokyo") if err != nil { log.Fatal(err) } tm := time.Now().In(jst) fmt.Println(tm) } 4 Embedded tzdata package: σϞ
35 $ GOOS=linux go1.15beta1 build -o jst main.go $ docker
build -t jst:latest . $ docker run --rm jst:latest 2020-07-11 16:52:27.389673074 +0900 JST 4 Embedded tzdata package: σϞ
36 • छʑͷڥͰΘΕΔιϑτΣΞΛ͢Δͱ͖ʹબࢶͱͯ͠ ༗༻ʹͳΓಘΔ • Α͘ΘΕΔύοέʔδͷ෦Ͱ LoadLocation ΘΕ͍ͯΔ • github.com/go-sql-driver/mysql
• github.com/lib/pq • …etc • tzdata ͠͠ߋ৽͞ΕΔ • OSͳͲͰέΞ͢Δ͔ɺΞϓϦέʔγϣϯଆͰέΞ͢Δ͔ͷ ͳͷͰಛੑΛΘ͔͍ͬͯΕΑ͍ 4 Embedded tzdata package
·ͱΊ 37 5 ·ͱΊ • Timezone ͷڥʹґଘ͍ͯ͠Δ • Go1.15 ͔Β
tzdata ຒΊࠐΈ͕Ͱ͖ΔΑ͏ʹͳΓڥґଘΛٵ ऩ͢Δखஈ͕૿͑Δ
͓ΘΓ