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
Enabling DevOps and Team Topologies Through Architecture: Architecting for Fast Flow
cer
PRO
0
340
A Journey of Contribution and Collaboration in Open Source
ivargrimstad
0
960
Figma Dev Modeで変わる!Flutterの開発体験
watanave
0
140
CSC509 Lecture 09
javiergs
PRO
0
140
ECS Service Connectのこれまでのアップデートと今後のRoadmapを見てみる
tkikuc
2
250
役立つログに取り組もう
irof
28
9.6k
Arm移行タイムアタック
qnighy
0
330
Click-free releases & the making of a CLI app
oheyadam
2
120
Jakarta EE meets AI
ivargrimstad
0
200
Jakarta EE meets AI
ivargrimstad
0
590
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
1
100
CSC509 Lecture 13
javiergs
PRO
0
110
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
How GitHub (no longer) Works
holman
310
140k
The Pragmatic Product Professional
lauravandoore
31
6.3k
Statistics for Hackers
jakevdp
796
220k
Making the Leap to Tech Lead
cromwellryan
133
8.9k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.9k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Code Reviewing Like a Champion
maltzj
520
39k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
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