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.4k
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
Carving the Way to Ruby Engineering
koic
3
440
Beyond the RuboCop Defaults
koic
3
3k
Minify Ruby Code
koic
2
2.2k
Permanent Agility
koic
37
7.7k
RuboCop: LSP and Prism
koic
3
4.2k
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
Other Decks in Programming
See All in Programming
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
350
Scalaから始めるOpenFeature入門 / Scalaわいわい勉強会 #4
arthur1
1
300
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
バグを見つけた?それAppleに直してもらおう!
uetyo
0
170
20年もののレガシープロダクトに 0からPHPStanを入れるまで / phpcon2024
hirobe1999
0
110
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
2
460
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
Security_for_introducing_eBPF
kentatada
0
110
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
0
160
42 best practices for Symfony, a decade later
tucksaun
1
180
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
250
コンテナをたくさん詰め込んだシステムとランタイムの変化
makihiro
1
120
Featured
See All Featured
Code Review Best Practice
trishagee
65
17k
Making Projects Easy
brettharned
116
5.9k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Practical Orchestrator
shlominoach
186
10k
Building a Scalable Design System with Sketch
lauravandoore
460
33k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
The Cost Of JavaScript in 2023
addyosmani
45
7k
A Philosophy of Restraint
colly
203
16k
Designing for Performance
lara
604
68k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
8.3k
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