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.4k
バンドルカードの クレジットカード決済システムの 泥臭い運用
hiroakis
10
8.9k
クレジットカードの通信プロトコル ISO8583 と戦う
hiroakis
31
14k
トレタのインフラ運用
hiroakis
8
5.2k
Other Decks in Programming
See All in Programming
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
800
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
360
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4.2k
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
2.3k
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
350
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.4k
スマートグラスで並列バイブコーディング
hyshu
0
290
霧の中の代数的エフェクト
funnyycat
1
340
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
310
1B+ /day規模のログを管理する技術
broadleaf
0
130
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
250
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Accessibility Awareness
sabderemane
1
150
Optimising Largest Contentful Paint
csswizardry
37
3.8k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
How to Talk to Developers About Accessibility
jct
2
340
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
750
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
AI: The stuff that nobody shows you
jnunemaker
PRO
8
820
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 ຒΊࠐΈ͕Ͱ͖ΔΑ͏ʹͳΓڥґଘΛٵ ऩ͢Δखஈ͕૿͑Δ
͓ΘΓ