Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
3k
バンドルカードの クレジットカード決済システムの 泥臭い運用
hiroakis
10
9k
クレジットカードの通信プロトコル ISO8583 と戦う
hiroakis
31
14k
トレタのインフラ運用
hiroakis
8
5.3k
Other Decks in Programming
See All in Programming
AWSに止められる覚悟してますか?
morizo_1984
2
530
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
420
外から家のPCの電源入れたい!をPHPで解決する
kawashimo0
1
130
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
0
430
Verilogで学ぶCPU自作入門
uyuki234
8
4.1k
カツオ、ご期待ください
suneo3476
0
190
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
4
3.4k
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.2k
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.2k
Featured
See All Featured
The untapped power of vector embeddings
frankvandijk
2
1.9k
Raft: Consensus for Rubyists
vanstee
142
7.8k
Producing Creativity
orderedlist
PRO
348
41k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
エンジニアに許された特別な時間の終わり
watany
109
250k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
330
Building Adaptive Systems
keathley
44
3.2k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
630
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 ຒΊࠐΈ͕Ͱ͖ΔΑ͏ʹͳΓڥґଘΛٵ ऩ͢Δखஈ͕૿͑Δ
͓ΘΓ