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
Road to RuboCop 1.0
Search
Koichi ITO
September 04, 2020
Programming
1
6.3k
Road to RuboCop 1.0
RubyKaigi Takeout 2020 Day1
Video:
https://www.youtube.com/watch?v=jkY7J9k6mHs&feature=emb_logo
Koichi ITO
September 04, 2020
Tweet
Share
More Decks by Koichi ITO
See All by Koichi ITO
Beyond the RuboCop Defaults
koic
3
2.7k
Minify Ruby Code
koic
2
2.1k
Permanent Agility
koic
37
7.5k
RuboCop: LSP and Prism
koic
3
4.1k
Organizational Pattern Hatching
koic
0
1.5k
A Practitioner's Journey from Ruby 1.8 to Present
koic
1
2k
A Story Featuring Right Hand Archetype
koic
0
1.1k
Without Practice, No Emergence
koic
4
2.4k
The Resurrection of the Fast Parallel Test Runner
koic
1
6.2k
Other Decks in Programming
See All in Programming
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.8k
タクシーアプリ『GO』のリアルタイムデータ分析基盤における機械学習サービスの活用
mot_techtalk
4
1.4k
Creating a Free Video Ad Network on the Edge
mizoguchicoji
0
110
詳細解説! ArrayListの仕組みと実装
yujisoftware
0
580
Less waste, more joy, and a lot more green: How Quarkus makes Java better
hollycummins
0
100
役立つログに取り組もう
irof
28
9.6k
Outline View in SwiftUI
1024jp
1
320
Make Impossible States Impossibleを 意識してReactのPropsを設計しよう
ikumatadokoro
0
170
Click-free releases & the making of a CLI app
oheyadam
2
110
Remix on Hono on Cloudflare Workers
yusukebe
1
280
Kaigi on Rails 2024 〜運営の裏側〜
krpk1900
1
190
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
47
2.1k
Optimizing for Happiness
mojombo
376
70k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
Embracing the Ebb and Flow
colly
84
4.5k
Practical Orchestrator
shlominoach
186
10k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Docker and Python
trallard
40
3.1k
Faster Mobile Websites
deanohume
305
30k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
Writing Fast Ruby
sferik
627
61k
Transcript
Road to RuboCop 1.0 ,PJDIJ*50&4. *OD 3VCZ,BJHJ5BLFPVU Ride on RuboCop
1.0 for safe static analysis
!LPJD w 3VCP$PQDPSFUFBN w 044QSPHSBNNFS w 5FDITQFBLFS w %JTUJOHVJTIFE&OHJOFFSBU &4.
*OD
&4. *OD
Support OSS community
None
#VOEMFS 1SZ 34QFD 3VCP$PQ CZFCVH 3VCZ,BJHJ %3&$0.CPPUI
None
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .PSFUIBODPOUSJCVUPSTJOZFBST
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 "VUIPS .PSFUIBODPOUSJCVUPSTJOZFBST
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .F .PSFUIBODPOUSJCVUPSTJOZFBST
3VCP$PQ"SDIJUFDUVSF
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ"45QBSTFS 3VCP$PQ"SDIJUFDUVSF 1BSTFSHFN 3VCP$PQ"45
3VCP$PQDPSF 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ"45QBSTFS $VTUPN$PQT 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
$PQTHFNJpFE CZ3VCP$PQ)2
3VCP$PQDPSF 1BTU"SDIJUFDUVSF 1BSTFSHFN 3VCP$PQ 34QFD
(FNJpFEDPQT
SVCPDPQIRSVCPDPQ &YUSBDU1FSGPSNBODF$PQTJOUPBTFQBSBUFHFN
None
3VCP$PQDPSF 'JSTUFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF &YUSBDUFE
None
None
+VBOJUP'BUBTGBTUSVCZSFQP
SBJMTSBJMT
#FODINBSLJQT require 'benchmark/ips' SLUG = 'writing-fast-ruby' def slow SLUG.gsub('-', '
') end def fast SLUG.tr('-', ' ') end Benchmark.ips do |x| x.report('String#gsub') { slow } x.report('String#tr') { fast } x.compare! end % ruby -v gsub-vs-tr.rb ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin17] Warming up -------------------------------------- String#gsub 59.463k i/100ms String#tr 296.069k i/100ms Calculating ------------------------------------- String#gsub 598.537k (± 1.8%) i/s - 3.033M in 5.068466s String#tr 2.955M (± 0.9%) i/s - 14.803M in 5.009464s Comparison: String#tr: 2955357.8 i/s String#gsub: 598537.4 i/s - 4.94x (± 0.00) slower
w 3VCP$PQDPSFGPDVTPOQMBUGPSN JOEFQFOEFOU3VCZQFSGPSNBODF w 1FSGPSNBODFDPQGPDVTPO.3*`T QFSGPSNBODF w 5IFpSTUFYUSBDUFEHFN 3VCP$PQ (FNJGZOPUFT
w'JSTU `cp`DPNNBOEUPDPQZ GSPNUIFQFSGPSNBODFDPQ pMFTUPUIFOFXSFQPTJUPSZ w*UTFBTZ CVUJUSFNPWFTGit IJTUPSZ )PXXPVMEZPVHFNJGZ
w.BJOUBJOFSTXBOUUPUSBDF UIFSFBTPOGPSDIBOHFT GSPNUIFDIBOHFIJTUPSZ w*XPVMEMJLFUPLFFQ DPOUSJCVUPSOBNF (JUIJTUPSZJTNBUUFS
w*BTLFE!BNBUTVEB IPX,BNJOBSJEJWJEFE SFOEFSJOHFOHJOFT )PXXBTUIFSFQPTJUPSZLFQUIJTUPSZ
l *VTFEHJUDIFSSZQJDL XIFO*HBNJpFE,BNJOBSJ⚡ !BNBUTVEB
MPDBM SFNPUF(JU)VC 3VCP$PQ1FSGPSNBODF 1VMMOFXSFQP 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF #BTFEPO 3VCP$PQ34QFD TUSVDUVSF %
git remote add upstream-performance \ <rubocop-performance URL> % git pull upstream-performance
MPDBM SFNPUF(JU)VC 3VCP$PQ1FSGPSNBODF 'FUDIPSJHJOBMSFQP 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF % git remote add
upstream-core \ <rubocop URL> % git fetch upstream-core
MPDBM SFNPUF(JU)VC 3FQFBUDIFSSZQJDLT 3VCP$PQ1FSGPSNBODF .BOZNBOZ HJUDIFSSZQJDL 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF % git
cherry-pick 7cbfa5a <hash of core> % git cherry-pick 7cbfa5a % git cherry-pick ...
MPDBM # DONE! % git push origin master SFNPUF(JU)VC 1VTIOFXSFQP
3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF 3VCP$PQ1FSGPSNBODF
wPWFSDIFSSZQJDLT )PXNBOZDIFSSZQJDLT % git log --oneline lib/rubocop/cop/performance \ spec/rubocop/cop/performance |
wc -l 225 % git log --oneline lib/rubocop/cop/rails \ spec/rubocop/cop/rails | wc -l 315 *NOPUTVSFJUJTUIFCFTUPQUJPO
SVCPDPQIRSVCPDPQ &YUSBDU3BJMT$PQTJOBTFQBSBUF
None
3VCP$PQDPSF 4FDPOEFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT &YUSBDUFE
None
w 3VCP$PQDPSFXJMMOPUTVQQPSU GSBNFXPSLTQFDJpDDPQT w 3VCP$PQ3BJMTOPXEFQFOETPO3BDL HFN w 5IFTFDPOEFYUSBDUFEHFN 3VCP$PQ
w 5IF3VCP$PQ3BJMTWFSTJPOJT (FNJGZOPUFT
lSVCPDPQSBJMTz FYJTUFEUP HFNJGZ SVCPDPQZNMJO SBJMTSBJMTSFQP /BNFTQBDFQSPCMFN 3VCP$PQ3BJMTW
None
w3VCP$PQ3BJMTWNJHSBUFE UPSVCPDPQSBJMT@DPOpHHFN w3VCP$PQ3BJMTWFYUSBDUFE 3BJMTDPQTGSPN3VCP$PQ DPSF 3VCP$PQ3BJMTWBOEW
w3VCP$PQ3BJMTXJMMESPQ 3BJMTTVQQPSU w3VCP$PQ3BJMTXJMMOPU BDDFQUDPQTGPSPMEFS3BJMT 3VCP$PQ3BJMTQMBOOFEDIBOHFT
3VCP$PQDPSF $VTUPN$PQT 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF $VTUPN$PQ
None
w(FOFSBUFTEJSFDUPSZ TUSVDUVSFGPSZPVSHFN w$POUBJOTNPOLFZQBUDI DPEF #BELOPXIPX SVCPDPQFYUFOTJPOHFOFSBUPS
.POLFZQBUDIPO 3VCP$PQDPSF
w:PVDBODSFBUFBOFXSEQBSUZ 3VCP$PQHFNUPTVQQPSUMJCSBSZ TQFDJpD ZPVSQSPKFDU SFRVJSFNFOUT FUD w:PVDBOIBOEMFEPNBJO LOPXMFEHF 8IFOEPZPVDSFBUFBSEQBSUZHFN
SVCPDPQIRSVCPDPQSBJMT "EEOFXA3BJMT/FX(MPCBM.PEFMADPQ
1SPQPTBMTGPS &OGPSDF3BJMT&OHJOF
3VCP$PQ3BJMTUBSHFUTl3BJMTXBZz
IUUQTqFYQPSUFOHJOFFSJOHJTPMBUJOHSBJMTFOHJOFTXJUISVCPDPQGFBCB
3VCP$PQ"1*W
SVCPDPQIRSVCPDPQ *NQSPWJOHBVUPDPSSFDUJPOT"1*
< Base FYUFOE"VUP$PSSFDUPS EPcDPSSFDUPSc
w0ME"1*TXJMMOPUCFSFNPWFE TPPO CVU`Cop::Base`JT TUSPOHMZSFDPNNFOEFEOPX w4FFl6QHSBEF/PUFTzGPS EFUBJMT &YUFOTJPO"1*DIBOHFEGPSW
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQ"45 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
SVCPDPQIRSVCPDPQ 6TJOHSVCPDPQBTU
3VCP$PQDPSF 1BTU"SDIJUFDUVSF W 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
5IJSEFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ"45 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT 3VCP$PQDPSF
&YUSBDUFE
None
w*OUFOEFEOPUGPS3VCP$PQ VTFSTEJSFDUMZ w3FFL B$-*UPPMXBOUUPVTF OPEFQBUUFSOTJOEFQFOEFOUMZ GSPN3VCP$PQDPSF 3VCP$PQ"45
USPFTTOFSSFFL SVCPDPQ
3VCP$PQ"45/PEF1BUUFSO w &YUFOEFETZOUBYGPS FYQSFTTJOHOPEFT w 1BUUFSONBUDIJOHUP DBQUVSFNBUDIJOH WBMVFT w 0GUFOVTFEBTBO
BSHVNFOUPG def_node_matcher FUD IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEF@QBUUFSOSC
3VCP$PQ"45/PEF w *OIFSJUT1BSTFS BOEQSPWJEFT QSFEJDBUF NFUIPET w :PVDBOSFGFS 3VCP$PQ JNQMFNFOUBUJPOT
IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEFSC
3VCP$PQ"451SPDFTTFE4PVSDF require 'rubocop-ast' ast = RuboCop::AST::ProcessedSource.new( 'puts "hello"', 2.7 ).ast
#=>s(:send, nil, :puts, s(:str, "hello")) ast.class #=> RuboCop::AST::SendNode ast.send_type? #=> true ast.first_argument.basic_literal? #=> true
3VCP$PQ"455SBWFSTBM require 'rubocop-ast' include RuboCop::AST::Traversal # Event handler for `send`
node def on_send(node) 'hi' end walk(ast) #=> hi
w4VQQPSUTTUBUJDBOBMZTJTCZ QBSTJOH QBUUFSONBUDIJOH BOEFWFOUIBOEMJOH w3VCP$PQJTUIF3FGFSFODF *NQMFNFOUBUJPO 3VCP$PQ"45JTBIBSWFTUFEMJCSBSZ
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 1BSTFS 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
$PEFPG6OEFSXPSME
6OEFSUIF3VCP$PQ 1BSTFSHFN XIJUFRVBSLQBSTFS 3VCP$PQ"45 3VCP$PQ DPSF 0QBM 3VCZ/FYU :FU"OPUIFS "OBMZ[FS
3BDD
None
w3VCZQBSTFSXSJUUFOJO3VCZ w4VQQPSUT.3* +3VCZ 5SVGqF3VCZ w#/'JTXSJUUFOCZ3BDD CBTFEPOQBSTFZPG3VCZ 8IBU`T1BSTFSHFN
w/FX3VCZTZOUBYJOUSPEVDFEJO 1BSTFSBTFYQFSJNFOUBM w3VCP$PQ"45FYUFOET1BSTFS`T OFX"1* w$PQTDBOIBOEMFOFXTZOUBYUSFF OPEFT /FX3VCZTZOUBYDBOCFVTFEJO3VCP$PQ
XIJUFRVBSLQBSTFS SVCZZ"MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO
8BUDIQBSTFZ DEdTSDHJUIVCDPNSVCZSVCZ HJUMPHQQBSTFZ DPNNJUEBGEDFBEBCBBGCBDDF "VUIPS,B[VLJ5TVKJNPUPLB[VLJ!DBMMDDOFU %BUF4VO.BS "MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO EJ⒎HJUBQBSTFZCQBSTFZ JOEFYDDGCG
BQBSTFZ CQBSTFZ !! !!Q@LXBSHTQ@LXBSH Q@LXSFTU \ OFX@IBTI@QBUUFSO@UBJM Q OFX@VOJRVF@LFZ@IBTI Q ! ! ^
IUUQTHJUIVCDPNSVCZSVCZDPNNJUEBG
3VCZSFQPUFTUDPEF Trailing comma
QBSTFZ :BDD key: value key: value,
1VMM3FRVFTU
1BSTFSHFNUFTUDPEF 3VCZDPEF Trailing comma
#/'PG1BSTFSHFN 6TJOH3BDD key: value key: value,
$PNQBSFUXPPVUQVUT SVCZQBSTFW SVCZQBSTFCBTFEPOQBSTFSWFSTJPO SVCZQBSTFFDBTFQBUUFSOJO\B ^UIFOUSVF FOE DBTFNBUDI TFOEOJMQBUUFSO
JOQBUUFSO IBTIQBUUFSO QBJS TZNB JOU OJM USVF OJM SVCZQBSTFW SVCZQBSTFCBTFEPOQBSTFSWFSTJPO SVCZQBSTFFDBTFQBUUFSOJO\B^UIFOUSVF FOE DBTFNBUDI TFOEOJMQBUUFSO JOQBUUFSO IBTIQBUUFSO QBJS TZNB JOU OJM USVF OJM 4BNF"45
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS "SDIJUFDUVSFUPXBSET 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQ$PSF 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQDPSFVQEBUF 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF
3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
4BGFBOE 4BGF"VUP$PSSFDU
SVCPDPQIRSVCPDPQ *NQMFNFOUPQUJPOTUPSVOPOMZTBGFDPQTBOE TBGFBVUPDPSSFDUT
None
w3VCP$PQJTBTUBUJDBOBMZTJTUPPM BOESVOUJNFJOGPJTOPUBWBJMBCMF w'BMTFQPTJUJWFEFUFDUJPONBZIBQQFO w*ODPNQBUJCMFBVUPDPSFSFDUJPONBZ IBQQFO 8IZVOTBGF
&YBNQMFEFGBVMUZNM Lint/RaiseException: VersionAdded: 0.56 + Safe: false Style/DoubleNegation: VersionAdded: '0.19'
VersionChanged: '0.84' + SafeAutoCorrect: false
w*OEJDBUFTXIFUIFSUIFDPQ DBOZJFMEGBMTFQPTJUJWFT CZEFTJHO PSOPU 4BGF
&YBNQMF7BSJBCMF DPOTUBOU UZQFT # Performance/AncestorsInclude # bad A.ancestors.include?(B) # good
A <= B
None
w'BMTFQPTJUJWFGPS /PLPHJSJ9.-/PEFBODFTUPST w'SFRVFOUGBMTFQPTJUJWFTEVFUP UIFEJGGFSFODFCFUXFFO "DUJWF3FDPSEBOE1030JO3BJMT 6OTBGFBCPVUSFDFJWFSUZQF
w*OEJDBUFTXIFUIFSUIFBVUPDPSSFDUB DPQEPFTJTTBGF FRVJWBMFOU CZ EFTJHO w*GSafe: falseJTTFU UIFOSafeAutoCorrect: falseJTBMTPTFU
4BGF"VUP$PSSFDU
&YBNQMFAOJMAWBSJBCMF # Performance/StartWith cop # bad str =~ /\Aab/ #
good str.start_with?('ab')
w&SSPSJGUIFWBSJBCMFJTOJM w*UDBOCFBWPJEFECZBEEJOHB TBGFOBWJHBUJPOPQFSBUPS CVUJUJTOPUBMXBZTSJHIU 6OTBGFBCPVUOJMWBSJBCMF
&YBNQMFFYUFSOBMSFTPVSDFT # Rails/UniqBeforePluck cop # bad Model.pluck(:id).uniq # good Model.distinct.pluck(:id)
None
w$PNQBUJCJMJUZJTOPUHVBSBOUFFE CFUXFFO3VCZTuniqNFUIPE BOE3%#.`TDISTINCT w'PSFYBNQMF UIFEFGBVMU.Z42- DPMMBUJPOJTDBTFJOTFOTJUJWF 6OTBGFBCPVUFYUFSOBMSFTPVSDFT
3VCZ,BJHJDBODFMMFE
3VCPDPQ5ZQFE
803,*/130(3&44
SVCPDPQIRSVCPDPQ $-*PQUJPOTDIBOHFBVUPDPSSFDUOPXTBGFCZEFGBVMU
wTBGF wB BVUPDPSSFDU w" BVUPDPSSFDUBMM ASVCPDPQAPQUJPOTGPSTBGFVOTBGF
w"QQMZPOMZTBGFBVUPDPSSFDUJPO wGTUSJOHMJUFSBMDPNNFOUJTOPU BVUPDPSSFDUFECZEFGBVMUBTJU XBTCFGPSF #3&",*/($)"/(&⚠ B BVUPDPSSFDU
w"QQMZTBGFBOEVOTBGFBVUP DPSSFDUJPO w5IJTPQUJPOJTUIFTBNFABA CFIBWJPSPG3VCP$PQBOEMPXFS w-JLFAHJUCSBODIEAWTA%A " BVUPDPSSFDUBMM
/FXDPQTUBUVT
SVCPDPQIRSVCPDPQ .BLFJUQPTTJCMFUPFOBCMFEJTBCMFQFOEJOHDPQT
None
w/FXDPQTUBUVTTUBSUTXJUIQFOEJOH PSEJTBCMFE w"MMQFOEJOHDPQTBSFFOBCMFEXIFO UIFNBKPSWFSTJPOCVNQT w1MFBTFHJWFGFFECBDLJGZPVIBWF JTTVFTBCPVUOFXDPQT /FXDPQTUBUVT
4VQQPSUQPMJDZ
SVCPDPQIRSVCPDPQ 6QEBUFPCTPMFUFSVCJFTBOEBEEBEPDGPSDPNQBUJCJMJUZ
w3VCP$PQXJMMQSPWJEFTVQQPSU &0-FE3VCZGPSBCPVUBZFBS w1MFBTFNJHSBUFUPOFX WFSTJPOPG3VCZ 4VQQPSUQPMJDZ
None
0OFNPSFUIJOH
$VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF 3VCP$PQ
34QFD 3VCP$PQ 1FSGPSNBODF $POpHVSBUJPO SVCPDPQZNM #VJMUJODPQT
EPDTSVCPDPQPSH
)BQQZTPDJBMDPEJOH +0900 UTC+0200 +0300 +0800 -0400 XJUINBOZDPOUSJCVUPSTBOEZPV
3VCZ,BJHJNFNPSJBM