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
460
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
PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications
seike460
PRO
2
470
Scalaから始めるOpenFeature入門 / Scalaわいわい勉強会 #4
arthur1
1
340
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
utgwkk
2
390
テスト自動化失敗から再挑戦しチームにオーナーシップを委譲した話/STAC2024 macho
ma_cho29
1
1.3k
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
Go の GC の不得意な部分を克服したい
taiyow
3
790
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
190
Effective Signals in Angular 19+: Rules and Helpers @ngbe2024
manfredsteyer
PRO
0
140
htmxって知っていますか?次世代のHTML
hiro_ghap1
0
340
生成AIでGitHubソースコード取得して仕様書を作成
shukob
0
470
Recoilを剥がしている話
kirik
5
6.8k
Асинхронность неизбежна: как мы проектировали сервис уведомлений
lamodatech
0
820
Featured
See All Featured
Side Projects
sachag
452
42k
VelocityConf: Rendering Performance Case Studies
addyosmani
326
24k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
17
2.3k
A better future with KSS
kneath
238
17k
Reflections from 52 weeks, 52 projects
jeffersonlam
347
20k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
32
2.7k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
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