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
3.1k
バンドルカードの クレジットカード決済システムの 泥臭い運用
hiroakis
10
9k
クレジットカードの通信プロトコル ISO8583 と戦う
hiroakis
31
14k
トレタのインフラ運用
hiroakis
8
5.3k
Other Decks in Programming
See All in Programming
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
150
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
170
Performance Optimization With LLMs
xleitix
0
210
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.2k
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.8k
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
3
540
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
190
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
320
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.7k
クラウドゲーミングのパフォーマンス最適化に挑む / Cloud Gaming Performance Tuning
vivion
0
260
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
340
Web Framework Benchmark Battle 2026, Any%
a_matsuda
3
3k
Featured
See All Featured
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
310
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
940
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Color Theory Basics | Prateek | Gurzu
gurzu
1
500
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Faster Mobile Websites
deanohume
310
32k
Writing Fast Ruby
sferik
630
63k
YesSQL, Process and Tooling at Scale
rocio
174
15k
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 ຒΊࠐΈ͕Ͱ͖ΔΑ͏ʹͳΓڥґଘΛٵ ऩ͢Δखஈ͕૿͑Δ
͓ΘΓ