PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/cpanel/ea-ruby24/root/usr/share/gems/gems/tzinfo-1.2.5/lib/tzinfo
Viewing File: /opt/cpanel/ea-ruby24/root/usr/share/gems/gems/tzinfo-1.2.5/lib/tzinfo/timezone.rb
require 'date' require 'set' require 'thread_safe' module TZInfo # AmbiguousTime is raised to indicates that a specified time in a local # timezone has more than one possible equivalent UTC time. This happens when # transitioning from daylight savings time to standard time where the clocks # are rolled back. # # AmbiguousTime is raised by period_for_local and local_to_utc when using an # ambiguous time and not specifying any means to resolve the ambiguity. class AmbiguousTime < StandardError end # PeriodNotFound is raised to indicate that no TimezonePeriod matching a given # time could be found. class PeriodNotFound < StandardError end # Raised by Timezone#get if the identifier given is not valid. class InvalidTimezoneIdentifier < StandardError end # Raised if an attempt is made to use a timezone created with # Timezone.new(nil). class UnknownTimezone < StandardError end # Timezone is the base class of all timezones. It provides a factory method, # 'get', to access timezones by identifier. Once a specific Timezone has been # retrieved, DateTimes, Times and timestamps can be converted between the UTC # and the local time for the zone. For example: # # tz = TZInfo::Timezone.get('America/New_York') # puts tz.utc_to_local(DateTime.new(2005,8,29,15,35,0)).to_s # puts tz.local_to_utc(Time.utc(2005,8,29,11,35,0)).to_s # puts tz.utc_to_local(1125315300).to_s # # Each time conversion method returns an object of the same type it was # passed. # # The Timezone class is thread-safe. It is safe to use class and instance # methods of Timezone in concurrently executing threads. Instances of Timezone # can be shared across thread boundaries. class Timezone include Comparable # Cache of loaded zones by identifier to avoid using require if a zone # has already been loaded. # # @!visibility private @@loaded_zones = nil # Default value of the dst parameter of the local_to_utc and # period_for_local methods. # # @!visibility private @@default_dst = nil # Sets the default value of the optional dst parameter of the # local_to_utc and period_for_local methods. Can be set to nil, true or # false. # # The value of default_dst defaults to nil if unset. def self.default_dst=(value) @@default_dst = value.nil? ? nil : !!value end # Gets the default value of the optional dst parameter of the # local_to_utc and period_for_local methods. Can be set to nil, true or # false. def self.default_dst @@default_dst end # Returns a timezone by its identifier (e.g. "Europe/London", # "America/Chicago" or "UTC"). # # Raises InvalidTimezoneIdentifier if the timezone couldn't be found. def self.get(identifier) instance = @@loaded_zones[identifier] unless instance # Thread-safety: It is possible that multiple equivalent Timezone # instances could be created here in concurrently executing threads. # The consequences of this are that the data may be loaded more than # once (depending on the data source) and memoized calculations could # be discarded. The performance benefit of ensuring that only a single # instance is created is unlikely to be worth the overhead of only # allowing one Timezone to be loaded at a time. info = data_source.load_timezone_info(identifier) instance = info.create_timezone @@loaded_zones[instance.identifier] = instance end instance end # Returns a proxy for the Timezone with the given identifier. The proxy # will cause the real timezone to be loaded when an attempt is made to # find a period or convert a time. get_proxy will not validate the # identifier. If an invalid identifier is specified, no exception will be # raised until the proxy is used. def self.get_proxy(identifier) TimezoneProxy.new(identifier) end # If identifier is nil calls super(), otherwise calls get. An identfier # should always be passed in when called externally. def self.new(identifier = nil) if identifier get(identifier) else super() end end # Returns an array containing all the available Timezones. # # Returns TimezoneProxy objects to avoid the overhead of loading Timezone # definitions until a conversion is actually required. def self.all get_proxies(all_identifiers) end # Returns an array containing the identifiers of all the available # Timezones. def self.all_identifiers data_source.timezone_identifiers end # Returns an array containing all the available Timezones that are based # on data (are not links to other Timezones). # # Returns TimezoneProxy objects to avoid the overhead of loading Timezone # definitions until a conversion is actually required. def self.all_data_zones get_proxies(all_data_zone_identifiers) end # Returns an array containing the identifiers of all the available # Timezones that are based on data (are not links to other Timezones).. def self.all_data_zone_identifiers data_source.data_timezone_identifiers end # Returns an array containing all the available Timezones that are links # to other Timezones. # # Returns TimezoneProxy objects to avoid the overhead of loading Timezone # definitions until a conversion is actually required. def self.all_linked_zones get_proxies(all_linked_zone_identifiers) end # Returns an array containing the identifiers of all the available # Timezones that are links to other Timezones. def self.all_linked_zone_identifiers data_source.linked_timezone_identifiers end # Returns all the Timezones defined for all Countries. This is not the # complete set of Timezones as some are not country specific (e.g. # 'Etc/GMT'). # # Returns TimezoneProxy objects to avoid the overhead of loading Timezone # definitions until a conversion is actually required. def self.all_country_zones Country.all_codes.inject([]) do |zones,country| zones += Country.get(country).zones end.uniq end # Returns all the zone identifiers defined for all Countries. This is not the # complete set of zone identifiers as some are not country specific (e.g. # 'Etc/GMT'). You can obtain a Timezone instance for a given identifier # with the get method. def self.all_country_zone_identifiers Country.all_codes.inject([]) do |zones,country| zones += Country.get(country).zone_identifiers end.uniq end # Returns all US Timezone instances. A shortcut for # TZInfo::Country.get('US').zones. # # Returns TimezoneProxy objects to avoid the overhead of loading Timezone # definitions until a conversion is actually required. def self.us_zones Country.get('US').zones end # Returns all US zone identifiers. A shortcut for # TZInfo::Country.get('US').zone_identifiers. def self.us_zone_identifiers Country.get('US').zone_identifiers end # The identifier of the timezone, e.g. "Europe/Paris". def identifier raise_unknown_timezone end # An alias for identifier. def name # Don't use alias, as identifier gets overridden. identifier end # Returns a friendlier version of the identifier. def to_s friendly_identifier end # Returns internal object state as a programmer-readable string. def inspect "#<#{self.class}: #{identifier}>" end # Returns a friendlier version of the identifier. Set skip_first_part to # omit the first part of the identifier (typically a region name) where # there is more than one part. # # For example: # # Timezone.get('Europe/Paris').friendly_identifier(false) #=> "Europe - Paris" # Timezone.get('Europe/Paris').friendly_identifier(true) #=> "Paris" # Timezone.get('America/Indiana/Knox').friendly_identifier(false) #=> "America - Knox, Indiana" # Timezone.get('America/Indiana/Knox').friendly_identifier(true) #=> "Knox, Indiana" def friendly_identifier(skip_first_part = false) parts = identifier.split('/') if parts.empty? # shouldn't happen identifier elsif parts.length == 1 parts[0] else prefix = skip_first_part ? nil : "#{parts[0]} - " parts = parts.drop(1).map do |part| part.gsub!(/_/, ' ') if part.index(/[a-z]/) # Missing a space if a lower case followed by an upper case and the # name isn't McXxxx. part.gsub!(/([^M][a-z])([A-Z])/, '\1 \2') part.gsub!(/([M][a-bd-z])([A-Z])/, '\1 \2') # Missing an apostrophe if two consecutive upper case characters. part.gsub!(/([A-Z])([A-Z])/, '\1\'\2') end part end "#{prefix}#{parts.reverse.join(', ')}" end end # Returns the TimezonePeriod for the given UTC time. utc can either be # a DateTime, Time or integer timestamp (Time.to_i). Any timezone # information in utc is ignored (it is treated as a UTC time). def period_for_utc(utc) raise_unknown_timezone end # Returns the set of TimezonePeriod instances that are valid for the given # local time as an array. If you just want a single period, use # period_for_local instead and specify how ambiguities should be resolved. # Returns an empty array if no periods are found for the given time. def periods_for_local(local) raise_unknown_timezone end # Returns an Array of TimezoneTransition instances representing the times # where the UTC offset of the timezone changes. # # Transitions are returned up to a given date and time up to a given date # and time, specified in UTC (utc_to). # # A from date and time may also be supplied using the utc_from parameter # (also specified in UTC). If utc_from is not nil, only transitions from # that date and time onwards will be returned. # # Comparisons with utc_to are exclusive. Comparisons with utc_from are # inclusive. If a transition falls precisely on utc_to, it will be excluded. # If a transition falls on utc_from, it will be included. # # Transitions returned are ordered by when they occur, from earliest to # latest. # # utc_to and utc_from can be specified using either DateTime, Time or # integer timestamps (Time.to_i). # # If utc_from is specified and utc_to is not greater than utc_from, then # transitions_up_to raises an ArgumentError exception. def transitions_up_to(utc_to, utc_from = nil) raise_unknown_timezone end # Returns the canonical Timezone instance for this Timezone. # # The IANA Time Zone database contains two types of definition: Zones and # Links. Zones are defined by rules that set out when transitions occur. # Links are just references to fully defined Zone, creating an alias for # that Zone. # # Links are commonly used where a time zone has been renamed in a # release of the Time Zone database. For example, the Zone US/Eastern was # renamed as America/New_York. A US/Eastern Link was added in its place, # linking to (and creating an alias for) for America/New_York. # # Links are also used for time zones that are currently identical to a full # Zone, but that are administered seperately. For example, Europe/Vatican is # a Link to (and alias for) Europe/Rome. # # For a full Zone, canonical_zone returns self. # # For a Link, canonical_zone returns a Timezone instance representing the # full Zone that the link targets. # # TZInfo can be used with different data sources (see the documentation for # TZInfo::DataSource). Please note that some DataSource implementations may # not support distinguishing between full Zones and Links and will treat all # time zones as full Zones. In this case, the canonical_zone will always # return self. # # There are two built-in DataSource implementations. RubyDataSource (which # will be used if the tzinfo-data gem is available) supports Link zones. # ZoneinfoDataSource returns Link zones as if they were full Zones. If the # canonical_zone or canonical_identifier methods are required, the # tzinfo-data gem should be installed. # # The TZInfo::DataSource.get method can be used to check which DataSource # implementation is being used. def canonical_zone raise_unknown_timezone end # Returns the TimezonePeriod for the given local time. local can either be # a DateTime, Time or integer timestamp (Time.to_i). Any timezone # information in local is ignored (it is treated as a time in the current # timezone). # # Warning: There are local times that have no equivalent UTC times (e.g. # in the transition from standard time to daylight savings time). There are # also local times that have more than one UTC equivalent (e.g. in the # transition from daylight savings time to standard time). # # In the first case (no equivalent UTC time), a PeriodNotFound exception # will be raised. # # In the second case (more than one equivalent UTC time), an AmbiguousTime # exception will be raised unless the optional dst parameter or block # handles the ambiguity. # # If the ambiguity is due to a transition from daylight savings time to # standard time, the dst parameter can be used to select whether the # daylight savings time or local time is used. For example, # # Timezone.get('America/New_York').period_for_local(DateTime.new(2004,10,31,1,30,0)) # # would raise an AmbiguousTime exception. # # Specifying dst=true would the daylight savings period from April to # October 2004. Specifying dst=false would return the standard period # from October 2004 to April 2005. # # If the dst parameter does not resolve the ambiguity, and a block is # specified, it is called. The block must take a single parameter - an # array of the periods that need to be resolved. The block can select and # return a single period or return nil or an empty array # to cause an AmbiguousTime exception to be raised. # # The default value of the dst parameter can be specified by setting # Timezone.default_dst. If default_dst is not set, or is set to nil, then # an AmbiguousTime exception will be raised in ambiguous situations unless # a block is given to resolve the ambiguity. def period_for_local(local, dst = Timezone.default_dst) results = periods_for_local(local) if results.empty? raise PeriodNotFound elsif results.size < 2 results.first else # ambiguous result try to resolve if !dst.nil? matches = results.find_all {|period| period.dst? == dst} results = matches if !matches.empty? end if results.size < 2 results.first else # still ambiguous, try the block if block_given? results = yield results end if results.is_a?(TimezonePeriod) results elsif results && results.size == 1 results.first else raise AmbiguousTime, "#{local} is an ambiguous local time." end end end end # Converts a time in UTC to the local timezone. utc can either be # a DateTime, Time or timestamp (Time.to_i). The returned time has the same # type as utc. Any timezone information in utc is ignored (it is treated as # a UTC time). def utc_to_local(utc) TimeOrDateTime.wrap(utc) {|wrapped| period_for_utc(wrapped).to_local(wrapped) } end # Converts a time in the local timezone to UTC. local can either be # a DateTime, Time or timestamp (Time.to_i). The returned time has the same # type as local. Any timezone information in local is ignored (it is treated # as a local time). # # Warning: There are local times that have no equivalent UTC times (e.g. # in the transition from standard time to daylight savings time). There are # also local times that have more than one UTC equivalent (e.g. in the # transition from daylight savings time to standard time). # # In the first case (no equivalent UTC time), a PeriodNotFound exception # will be raised. # # In the second case (more than one equivalent UTC time), an AmbiguousTime # exception will be raised unless the optional dst parameter or block # handles the ambiguity. # # If the ambiguity is due to a transition from daylight savings time to # standard time, the dst parameter can be used to select whether the # daylight savings time or local time is used. For example, # # Timezone.get('America/New_York').local_to_utc(DateTime.new(2004,10,31,1,30,0)) # # would raise an AmbiguousTime exception. # # Specifying dst=true would return 2004-10-31 5:30:00. Specifying dst=false # would return 2004-10-31 6:30:00. # # If the dst parameter does not resolve the ambiguity, and a block is # specified, it is called. The block must take a single parameter - an # array of the periods that need to be resolved. The block can return a # single period to use to convert the time or return nil or an empty array # to cause an AmbiguousTime exception to be raised. # # The default value of the dst parameter can be specified by setting # Timezone.default_dst. If default_dst is not set, or is set to nil, then # an AmbiguousTime exception will be raised in ambiguous situations unless # a block is given to resolve the ambiguity. def local_to_utc(local, dst = Timezone.default_dst) TimeOrDateTime.wrap(local) {|wrapped| if block_given? period = period_for_local(wrapped, dst) {|periods| yield periods } else period = period_for_local(wrapped, dst) end period.to_utc(wrapped) } end # Returns information about offsets used by the Timezone up to a given # date and time, specified using UTC (utc_to). The information is returned # as an Array of TimezoneOffset instances. # # A from date and time may also be supplied using the utc_from parameter # (also specified in UTC). If utc_from is not nil, only offsets used from # that date and time forward will be returned. # # Comparisons with utc_to are exclusive. Comparisons with utc_from are # inclusive. # # Offsets may be returned in any order. # # utc_to and utc_from can be specified using either DateTime, Time or # integer timestamps (Time.to_i). # # If utc_from is specified and utc_to is not greater than utc_from, then # offsets_up_to raises an ArgumentError exception. def offsets_up_to(utc_to, utc_from = nil) utc_to = TimeOrDateTime.wrap(utc_to) transitions = transitions_up_to(utc_to, utc_from) if transitions.empty? # No transitions in the range, find the period that covers it. if utc_from # Use the from date as it is inclusive. period = period_for_utc(utc_from) else # utc_to is exclusive, so this can't be used with period_for_utc. # However, any time earlier than utc_to can be used. # Subtract 1 hour (since this is one of the cached OffsetRationals). # Use add_with_convert so that conversion to DateTime is performed if # required. period = period_for_utc(utc_to.add_with_convert(-3600)) end [period.offset] else result = Set.new first = transitions.first result << first.previous_offset unless utc_from && first.at == utc_from transitions.each do |t| result << t.offset end result.to_a end end # Returns the canonical identifier for this Timezone. # # This is a shortcut for calling canonical_zone.identifier. Please refer # to the canonical_zone documentation for further information. def canonical_identifier canonical_zone.identifier end # Returns the current time in the timezone as a Time. def now utc_to_local(Time.now.utc) end # Returns the TimezonePeriod for the current time. def current_period period_for_utc(Time.now.utc) end # Returns the current Time and TimezonePeriod as an array. The first element # is the time, the second element is the period. def current_period_and_time utc = Time.now.utc period = period_for_utc(utc) [period.to_local(utc), period] end alias :current_time_and_period :current_period_and_time # Converts a time in UTC to local time and returns it as a string according # to the given format. # # The formatting is identical to Time.strftime and DateTime.strftime, except # %Z and %z are replaced with the timezone abbreviation (for example, EST or # EDT) and offset for the specified Timezone and time. # # The offset can be formatted as follows: # # - %z - hour and minute (e.g. +0500) # - %:z - hour and minute separated with a colon (e.g. +05:00) # - %::z - hour minute and second separated with colons (e.g. +05:00:00) # - %:::z - hour only (e.g. +05) # # Timezone#strftime currently handles the replacement of %z. From TZInfo # version 2.0.0, %z will be passed to Time#strftime and DateTime#strftime # instead. Some of the formatting options may cease to be available # depending on the version of Ruby in use (for example, %:::z is only # supported by Time#strftime from MRI version 2.0.0 onwards.) def strftime(format, utc = Time.now.utc) period = period_for_utc(utc) local = period.to_local(utc) local = Time.at(local).utc unless local.kind_of?(Time) || local.kind_of?(DateTime) abbreviation = period.abbreviation.to_s.gsub(/%/, '%%') format = format.gsub(/%(%*)(Z|:*z)/) do if $1.length.odd? # Escaped literal percent or series of percents. Pass on to strftime. "#$1%#$2" elsif $2 == "Z" "#$1#{abbreviation}" else m, s = period.utc_total_offset.divmod(60) h, m = m.divmod(60) case $2.length when 1 "#$1#{'%+03d%02d' % [h,m]}" when 2 "#$1#{'%+03d:%02d' % [h,m]}" when 3 "#$1#{'%+03d:%02d:%02d' % [h,m,s]}" when 4 "#$1#{'%+03d' % [h]}" else # more than 3 colons - not a valid option # Passing the invalid format string through to Time#strftime or # DateTime#strtime would normally result in it being returned in the # result. However, with Ruby 1.8.7 on Windows (as tested with Ruby # 1.8.7-p374 from http://rubyinstaller.org/downloads/archives), this # causes Time#strftime to always return an empty string (e.g. # Time.now.strftime('a %::::z b') returns ''). # # Escape the percent to force it to be evaluated as a literal. "#$1%%#$2" end end end local.strftime(format) end # Compares two Timezones based on their identifier. Returns -1 if tz is less # than self, 0 if tz is equal to self and +1 if tz is greater than self. # # Returns nil if tz is not comparable with Timezone instances. def <=>(tz) return nil unless tz.is_a?(Timezone) identifier <=> tz.identifier end # Returns true if and only if the identifier of tz is equal to the # identifier of this Timezone. def eql?(tz) self == tz end # Returns a hash of this Timezone. def hash identifier.hash end # Dumps this Timezone for marshalling. def _dump(limit) identifier end # Loads a marshalled Timezone. def self._load(data) Timezone.get(data) end private # Initializes @@loaded_zones. def self.init_loaded_zones @@loaded_zones = ThreadSafe::Cache.new end init_loaded_zones # Returns an array of proxies corresponding to the given array of # identifiers. def self.get_proxies(identifiers) identifiers.collect {|identifier| get_proxy(identifier)} end # Returns the current DataSource. def self.data_source DataSource.get end # Raises an UnknownTimezone exception. def raise_unknown_timezone raise UnknownTimezone, 'TZInfo::Timezone constructed directly' end end end