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
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.1k
バンドルカードの クレジットカード決済システムの 泥臭い運用
hiroakis
10
8.9k
クレジットカードの通信プロトコル ISO8583 と戦う
hiroakis
31
14k
トレタのインフラ運用
hiroakis
8
5.2k
Other Decks in Programming
See All in Programming
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
330
OSもどきOS
arkw
0
600
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.5k
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
600
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.5k
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
120
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
310
1B+ /day規模のログを管理する技術
broadleaf
0
120
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
4
870
The NotImplementedError Problem in Ruby
koic
1
970
Oxlintのカスタムルールの現況
syumai
6
1.2k
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
560
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Rails Girls Zürich Keynote
gr2m
96
14k
Technical Leadership for Architectural Decision Making
baasie
3
420
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
170
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.7k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Crafting Experiences
bethany
1
190
Speed Design
sergeychernyshev
33
1.9k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
400
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
750
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
640
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 ຒΊࠐΈ͕Ͱ͖ΔΑ͏ʹͳΓڥґଘΛٵ ऩ͢Δखஈ͕૿͑Δ
͓ΘΓ