PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/opt/cpanel/ea-php81/root/usr/include/php/ext/date/lib/
Upload File :
Current File : //opt/cpanel/ea-php81/root/usr/include/php/ext/date/lib/timelib.h
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2022 Derick Rethans
 * Copyright (c) 2018,2021 MongoDB, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef __TIMELIB_H__
#define __TIMELIB_H__

#ifdef HAVE_TIMELIB_CONFIG_H
# include "timelib_config.h"
#endif

#define TIMELIB_VERSION 202119
#define TIMELIB_EXTENDED_VERSION 20211901
#define TIMELIB_ASCII_VERSION "2021.19"

#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <inttypes.h>

# ifndef HAVE_INT32_T
#  if SIZEOF_INT == 4
typedef int int32_t;
#  elif SIZEOF_LONG == 4
typedef long int int32_t;
#  endif
# endif

# ifndef HAVE_UINT32_T
#  if SIZEOF_INT == 4
typedef unsigned int uint32_t;
#  elif SIZEOF_LONG == 4
typedef unsigned long int uint32_t;
#  endif
# endif

#ifdef _WIN32
# if _MSC_VER >= 1600
# include <stdint.h>
# endif
# ifndef SIZEOF_INT
#  define SIZEOF_INT 4
# endif
# ifndef SIZEOF_LONG
#  define SIZEOF_LONG 4
# endif
# ifndef int32_t
typedef __int32           int32_t;
# endif
# ifndef uint32_t
typedef unsigned __int32  uint32_t;
# endif
# ifndef int64_t
typedef __int64           int64_t;
# endif
# ifndef uint64_t
typedef unsigned __int64  uint64_t;
# endif
# ifndef PRId32
#  define PRId32       "I32d"
# endif
# ifndef PRIu32
#  define PRIu32       "I32u"
# endif
# ifndef PRId64
#  define PRId64       "I64d"
# endif
# ifndef PRIu64
#  define PRIu64       "I64u"
# endif
# ifndef INT32_MAX
#define INT32_MAX    _I32_MAX
# endif
# ifndef INT32_MIN
#define INT32_MIN    ((int32_t)_I32_MIN)
# endif
# ifndef UINT32_MAX
#define UINT32_MAX   _UI32_MAX
# endif
# ifndef INT64_MIN
#define INT64_MIN    ((int64_t)_I64_MIN)
# endif
# ifndef INT64_MAX
#define INT64_MAX    _I64_MAX
# endif
# ifndef UINT64_MAX
#define UINT64_MAX   _UI64_MAX
# endif
#endif

#if (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) && !defined(TIMELIB_FORCE_LONG32)
typedef int64_t timelib_long;
typedef uint64_t timelib_ulong;
# define TIMELIB_LONG_MAX INT64_MAX
# define TIMELIB_LONG_MIN INT64_MIN
# define TIMELIB_ULONG_MAX UINT64_MAX
# define TIMELIB_LONG_FMT "%" PRId64
# define TIMELIB_ULONG_FMT "%" PRIu64
#else
typedef int32_t timelib_long;
typedef uint32_t timelib_ulong;
# define TIMELIB_LONG_MAX INT32_MAX
# define TIMELIB_LONG_MIN INT32_MIN
# define TIMELIB_ULONG_MAX UINT32_MAX
# define TIMELIB_LONG_FMT "%" PRId32
# define TIMELIB_ULONG_FMT "%" PRIu32
#endif

#if defined(_MSC_VER)
typedef uint64_t timelib_ull;
typedef int64_t timelib_sll;
# define TIMELIB_LL_CONST(n) n ## i64
#else
typedef unsigned long long timelib_ull;
typedef signed long long timelib_sll;
# define TIMELIB_LL_CONST(n) n ## ll
#endif

typedef struct _ttinfo ttinfo;
typedef struct _tlinfo tlinfo;

typedef struct _tlocinfo
{
	char country_code[3];
	double latitude;
	double longitude;
	char *comments;
} tlocinfo;

#define TIMELIB_POSIX_TRANS_TYPE_JULIAN_NO_FEB29   1
#define TIMELIB_POSIX_TRANS_TYPE_JULIAN_FEB29      2
#define TIMELIB_POSIX_TRANS_TYPE_MWD               3

typedef struct _timelib_posix_trans_info
{
	int type; // 1=Jn, 2=n, 3=Mm.w.d
	union {
		int days;
		struct {
			int month;
			int week;
			int dow;
		} mwd;
	};
	int hour;
} timelib_posix_trans_info;

typedef struct _timelib_posix_str
{
	char        *std;
	timelib_sll  std_offset;
	char        *dst;
	timelib_sll  dst_offset;

	timelib_posix_trans_info *dst_begin;
	timelib_posix_trans_info *dst_end;

	int type_index_std_type;  // index into tz->type
	int type_index_dst_type;  // index into tz->type
} timelib_posix_str;

typedef struct _timelib_posix_transitions {
	size_t      count;
	timelib_sll times[6];
	timelib_sll types[6];
} timelib_posix_transitions;

typedef struct _timelib_tzinfo
{
	char    *name;
	struct {
		uint32_t ttisgmtcnt;
		uint32_t ttisstdcnt;
		uint32_t leapcnt;
		uint32_t timecnt;
		uint32_t typecnt;
		uint32_t charcnt;
	} _bit32;
	struct {
		uint64_t ttisgmtcnt;
		uint64_t ttisstdcnt;
		uint64_t leapcnt;
		uint64_t timecnt;
		uint64_t typecnt;
		uint64_t charcnt;
	} bit64;

	int64_t *trans;
	unsigned char *trans_idx;

	ttinfo  *type;
	char    *timezone_abbr;

	tlinfo  *leap_times;
	unsigned char bc;
	tlocinfo location;

	char              *posix_string;
	timelib_posix_str *posix_info;
} timelib_tzinfo;

typedef struct _timelib_rel_time {
	timelib_sll y, m, d; /* Years, Months and Days */
	timelib_sll h, i, s; /* Hours, mInutes and Seconds */
	timelib_sll us;      /* Microseconds */

	int weekday; /* Stores the day in 'next monday' */
	int weekday_behavior; /* 0: the current day should *not* be counted when advancing forwards; 1: the current day *should* be counted */

	int first_last_day_of;
	int invert; /* Whether the difference should be inverted */
	timelib_sll days; /* Contains the number of *days*, instead of Y-M-D differences */

	struct {
		unsigned int type;
		timelib_sll amount;
	} special;

	unsigned int   have_weekday_relative, have_special_relative;
} timelib_rel_time;

typedef struct _timelib_time_offset {
	int32_t      offset;
	unsigned int leap_secs;
	unsigned int is_dst;
	char        *abbr;
	timelib_sll  transition_time;
} timelib_time_offset;

typedef struct _timelib_time {
	timelib_sll      y, m, d;     /* Year, Month, Day */
	timelib_sll      h, i, s;     /* Hour, mInute, Second */
	timelib_sll      us;          /* Microseconds */
	int              z;           /* UTC offset in seconds */
	char            *tz_abbr;     /* Timezone abbreviation (display only) */
	timelib_tzinfo  *tz_info;     /* Timezone structure */
	signed int       dst;         /* Flag if we were parsing a DST zone */
	timelib_rel_time relative;

	timelib_sll      sse;         /* Seconds since epoch */

	unsigned int   have_time, have_date, have_zone, have_relative, have_weeknr_day;

	unsigned int   sse_uptodate; /* !0 if the sse member is up to date with the date/time members */
	unsigned int   tim_uptodate; /* !0 if the date/time members are up to date with the sse member */
	unsigned int   is_localtime; /*  1 if the current struct represents localtime, 0 if it is in GMT */
	unsigned int   zone_type;    /*  1 time offset,
	                              *  3 TimeZone identifier,
	                              *  2 TimeZone abbreviation */
} timelib_time;

typedef struct _timelib_abbr_info {
	timelib_sll  utc_offset;
	char        *abbr;
	int          dst;
} timelib_abbr_info;

#define TIMELIB_WARN_MASK                      0x1ff
#define TIMELIB_ERR_MASK                       0x2ff

#define TIMELIB_WARN_DOUBLE_TZ                 0x101
#define TIMELIB_WARN_INVALID_TIME              0x102
#define TIMELIB_WARN_INVALID_DATE              0x103
#define TIMELIB_WARN_TRAILING_DATA             0x11a

#define TIMELIB_ERR_DOUBLE_TZ                  0x201
#define TIMELIB_ERR_TZID_NOT_FOUND             0x202
#define TIMELIB_ERR_DOUBLE_TIME                0x203
#define TIMELIB_ERR_DOUBLE_DATE                0x204
#define TIMELIB_ERR_UNEXPECTED_CHARACTER       0x205
#define TIMELIB_ERR_EMPTY_STRING               0x206
#define TIMELIB_ERR_UNEXPECTED_DATA            0x207
#define TIMELIB_ERR_NO_TEXTUAL_DAY             0x208
#define TIMELIB_ERR_NO_TWO_DIGIT_DAY           0x209
#define TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR 0x20a
#define TIMELIB_ERR_NO_TWO_DIGIT_MONTH         0x20b
#define TIMELIB_ERR_NO_TEXTUAL_MONTH           0x20c
#define TIMELIB_ERR_NO_TWO_DIGIT_YEAR          0x20d
#define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR         0x20e
#define TIMELIB_ERR_NO_TWO_DIGIT_HOUR          0x20f
#define TIMELIB_ERR_HOUR_LARGER_THAN_12        0x210
#define TIMELIB_ERR_MERIDIAN_BEFORE_HOUR       0x211
#define TIMELIB_ERR_NO_MERIDIAN                0x212
#define TIMELIB_ERR_NO_TWO_DIGIT_MINUTE        0x213
#define TIMELIB_ERR_NO_TWO_DIGIT_SECOND        0x214
#define TIMELIB_ERR_NO_SIX_DIGIT_MICROSECOND   0x215
#define TIMELIB_ERR_NO_SEP_SYMBOL              0x216
#define TIMELIB_ERR_EXPECTED_ESCAPE_CHAR       0x217
#define TIMELIB_ERR_NO_ESCAPED_CHAR            0x218
#define TIMELIB_ERR_WRONG_FORMAT_SEP           0x219
#define TIMELIB_ERR_TRAILING_DATA              0x21a
#define TIMELIB_ERR_DATA_MISSING               0x21b
#define TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND 0x21c
#define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO     0x21d
#define TIMELIB_ERR_NO_TWO_DIGIT_WEEK          0x21e
#define TIMELIB_ERR_INVALID_WEEK               0x21f
#define TIMELIB_ERR_NO_DAY_OF_WEEK             0x220
#define TIMELIB_ERR_INVALID_DAY_OF_WEEK        0x221
#define TIMELIB_ERR_INVALID_SPECIFIER          0x222
#define TIMELIB_ERR_INVALID_TZ_OFFSET          0x223
#define TIMELIB_ERR_FORMAT_LITERAL_MISMATCH    0x224
#define TIMELIB_ERR_MIX_ISO_WITH_NATURAL       0x225

#define TIMELIB_ZONETYPE_NONE   0
#define TIMELIB_ZONETYPE_OFFSET 1
#define TIMELIB_ZONETYPE_ABBR   2
#define TIMELIB_ZONETYPE_ID     3

typedef struct _timelib_error_message {
	int         error_code;
	int         position;
	char        character;
	char       *message;
} timelib_error_message;

typedef struct _timelib_error_container {
	timelib_error_message *error_messages;
	timelib_error_message *warning_messages;
	int                    error_count;
	int                    warning_count;
} timelib_error_container;

typedef struct _timelib_tz_lookup_table {
	const char *name;
	int         type;
	float       gmtoffset;
	const char *full_tz_name;
} timelib_tz_lookup_table;

typedef struct _timelib_tzdb_index_entry {
	char *id;
	unsigned int pos;
} timelib_tzdb_index_entry;

typedef struct _timelib_tzdb {
	const char                     *version;
	int                             index_size;
	const timelib_tzdb_index_entry *index;
	const unsigned char            *data;
} timelib_tzdb;

#ifndef timelib_malloc
# define timelib_malloc  malloc
# define timelib_realloc realloc
# define timelib_calloc  calloc
# define timelib_strdup  strdup
# define timelib_free    free
# if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#  define TIMELIB_USE_BUILTIN_STRNDUP 1
# else
#  define TIMELIB_USE_BUILTIN_STRNDUP 0
#  define timelib_strndup strndup
# endif
#endif

#define TIMELIB_NONE             0x00
#define TIMELIB_OVERRIDE_TIME    0x01
#define TIMELIB_NO_CLONE         0x02

#define TIMELIB_UNSET   -9999999

/* An entry for each of these error codes is also in the
 * timelib_error_messages array in timelib.c.
 * Codes 0x00, 0x07, and 0x09 are warnings only. */
#define TIMELIB_ERROR_NO_ERROR                            0x00
#define TIMELIB_ERROR_CANNOT_ALLOCATE                     0x01
#define TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE   0x02
#define TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE           0x03
#define TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION             0x04
#define TIMELIB_ERROR_UNSUPPORTED_VERSION                 0x05
#define TIMELIB_ERROR_NO_SUCH_TIMEZONE                    0x06
#define TIMELIB_ERROR_SLIM_FILE                           0x07 /* Warns if the file is SLIM, but we can't read it */
#define TIMELIB_ERROR_CORRUPT_POSIX_STRING                0x08
#define TIMELIB_ERROR_EMPTY_POSIX_STRING                  0x09 /* Warns if the POSIX string is empty, but still produces results */

#ifdef __cplusplus
extern "C" {
#endif

typedef enum _timelib_format_specifier_code {
	TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS = 0,
	TIMELIB_FORMAT_ANY_SEPARATOR,
	TIMELIB_FORMAT_DAY_TWO_DIGIT,
	TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED,
	TIMELIB_FORMAT_DAY_OF_WEEK_ISO,
	TIMELIB_FORMAT_DAY_OF_WEEK,
	TIMELIB_FORMAT_DAY_OF_YEAR,
	TIMELIB_FORMAT_DAY_SUFFIX,
	TIMELIB_FORMAT_END,
	TIMELIB_FORMAT_EPOCH_SECONDS,
	TIMELIB_FORMAT_ESCAPE,
	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX,
	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED,
	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX,
	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED,
	TIMELIB_FORMAT_LITERAL,
	TIMELIB_FORMAT_MERIDIAN,
	TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT,
	TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT,
	TIMELIB_FORMAT_MINUTE_TWO_DIGIT,
	TIMELIB_FORMAT_MONTH_TWO_DIGIT,
	TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED,
	TIMELIB_FORMAT_RANDOM_CHAR,
	TIMELIB_FORMAT_RESET_ALL,
	TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET,
	TIMELIB_FORMAT_SECOND_TWO_DIGIT,
	TIMELIB_FORMAT_SEPARATOR,
	TIMELIB_FORMAT_SKIP_TO_SEPARATOR,
	TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER,
	TIMELIB_FORMAT_TEXTUAL_DAY_FULL,
	TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER,
	TIMELIB_FORMAT_TEXTUAL_MONTH_FULL,
	TIMELIB_FORMAT_TIMEZONE_OFFSET,
	TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES,
	TIMELIB_FORMAT_WEEK_OF_YEAR_ISO,
	TIMELIB_FORMAT_WEEK_OF_YEAR,
	TIMELIB_FORMAT_WHITESPACE,
	TIMELIB_FORMAT_YEAR_TWO_DIGIT,
	TIMELIB_FORMAT_YEAR_FOUR_DIGIT,
	TIMELIB_FORMAT_YEAR_ISO
} timelib_format_specifier_code;

typedef struct _timelib_format_specifier {
	char                          specifier;
	timelib_format_specifier_code code;
} timelib_format_specifier;

typedef struct _timelib_format_config {
	const timelib_format_specifier *format_map;
	/* Format speciifiers must be preceded by 'prefix_char' if not '\0'. */
	char                            prefix_char;
} timelib_format_config;

/* Function pointers */
typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(const char *tzname, const timelib_tzdb *tzdb, int *error_code);

/* From dow.c */
/* Calculates the day of the week from y, m, and d. 0=Sunday..6=Saturday */
timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);

/* Calculates the day of the ISO week from y, m, and d. 1=Monday, 7=Sunday */
timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);

/* Calculates the day of the year according to y-m-d. 0=Jan 1st..364/365=Dec
 * 31st */
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d);

/* Calculates the day of the year according to y-w-dow. 0..364/365 */
timelib_sll timelib_daynr_from_weeknr(timelib_sll iy, timelib_sll iw, timelib_sll id);

/* Calculates the number of days in month m for year y. 28..31 */
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);

/* Calculates the ISO year and week from y, m, and d, into iw and iy */
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);

/* Calculates the ISO year, week, and day of week from y, m, and d, into iy,
 * iw, and id */
void timelib_isodate_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iy, timelib_sll *iw, timelib_sll *id);

/* Calculates the year, month, and day from iy, iw, and iw, into y, m, and d */
void timelib_date_from_isodate(timelib_sll iy, timelib_sll iw, timelib_sll id, timelib_sll *y, timelib_sll *m, timelib_sll *d);

/* Returns true if h, i and s fit in the range 00:00:00..23:59:59, false
 * otherwise */
int timelib_valid_time(timelib_sll h, timelib_sll i, timelib_sll s);

/* Returns true if m fits in the range 1..12, and d fits in the range
 * 1..<days-in-month> for year y */
int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d);

/* From parse_date.re */

/* Parses the date/time string in 's' with length 'len' into the constituent
 * parts of timelib_time*.
 *
 * Depending on the contents of the string 's', not all elements might be
 * filled. You can check whether a specific element has been parsed by
 * comparing with the TIMELIB_UNSET define.
 *
 * If errors occur, this function keeps already parsed elements in the
 * returned timelib_time* value.
 *
 * If the **errors points to a timelib_error_container variable, warnings
 * and errors will be recorded. You are responsible for freeing the stored
 * information with timelib_error_container_dtor(). To see whether errors have
 * occurred, inspect errors->errors_count. To see whether warnings have occurred,
 * inspect errors->warnings_count.
 *
 * The returned timelib_time* value is dynamically allocated and should be
 * freed with timelib_time_dtor().
 */
timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);

/* Parses the date/time string in 's' with length 'len' into the constituent
 * parts of timelib_time* according to the format in 'format'.
 *
 * Depending on the contents of the string 's', not all elements might be
 * filled. You can check whether a specific element has been parsed by
 * comparing with the TIMELIB_UNSET define.
 *
 * If errors occur, this function keeps already parsed elements in the
 * returned timelib_time* value.
 *
 * If the **errors points to a timelib_error_container variable, warnings
 * and errors will be recorded. You are responsible for freeing the stored
 * information with timelib_error_container_dtor(). To see whether errors have
 * occurred, inspect errors->errors_count. To see whether warnings have occurred,
 * inspect errors->warnings_count.
 *
 * The returned timelib_time* value is dynamically allocated and should be
 * freed with timelib_time_dtor().
 */
timelib_time *timelib_parse_from_format(const char *format, const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);

/* Parses the date/time string in 's' with length 'len' into the constituent
 * parts of timelib_time* according to the format in 'format' with format
 * specifier configuration 'format_config'.
 *
 * 'format_map' is an array of pairs, with the first element being the format
 * specifier as a character and the second element corresponds to the
 * representation of the specifier from the enum list
 * 'timelib_format_specifier_code'.
 *
 * Note: 'format_map' must be terminated with specifier '\0' to indicate to the
 * parser that there are no more format specifiers in the list.
 */
timelib_time *timelib_parse_from_format_with_map(const char *format, const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper, const timelib_format_config* format_config);

/* Fills the gaps in the parsed timelib_time with information from the reference date/time in 'now'
 *
 * If any of the 'parsed' y, m, d, h, i or s parameters is unset (TIMELIB_UNSET):
 * - if microtime (us) is unset, then the us of the parsed time is set to 0.
 * - else if microtime (us) is unset and 'now'->'us' is set, use it, otherwise use 0.
 *
 * For either of the 'parsed' y, m, d, h, i, s, z (utc offset in seconds) or
 * dst is unset, set it to the corresponding value in 'now' if set, otherwise
 * set it to 0.
 *
 * It duplicates tz_abbr if unset in 'parsed' but set in 'now'.
 *
 * It duplicates tz_info if unset in 'parsed', but set in 'now' unless
 * TIMELIB_NO_CLONE is passed, in which case only the pointer in 'parsed' is
 * set to 'now'.
 *
 * If the option TIMELIB_OVERRIDE_TIME is passed and the parsed date/time has
 * no time portion, the function will ignore the time aspect in 'now' and
 * instead fill it with zeros.
 */
void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);

/* Tries to convert a time zone abbreviation, gmtoffset and/or isdst flag
 * combination to a time zone identifier.
 *
 * If 'abbr' is either 'utc' or 'gmt' (case insensitve) then "UTC" is
 * returned.
 *
 * It first uses the data in the timezonemap.h file to find a matching
 * abbreviation/GMT offset combination. If not found, it uses the data in
 * fallbackmap.h to match only the GMT offset/isdst flag to try to find a
 * match. If nothing is found, NULL is returned.
 *
 * The returned char* is not duplicated, and should not be freed.
 */
const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst);

/* Returns an array of known time zone abbreviations
 *
 * This file is generated from the time zone database through the
 * gettzmapping.php scripts, which requires that an up-to-date time zone
 * database is used with the PHP binary that runs the script.
 *
 * Each item in the returned list contains the abbreviation, a flag whether
 * it's an abbreviation used with DST, the UTC offset in seconds, and the name
 * of the time zone identifier that this abbreviation belongs to.
 *
 * The order for each specific abbreviation is controlled through the
 * preference list in the gettzmapping.php script. Time zones that match the
 * pattern ±\d{2,4} are excluded
 */
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);

/**
 * DEPRECATED, but still used by PHP.
 */
timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper);

/* From parse_iso_intervals.re */

/**
 * Parses a subset of an ISO 8601 intervals specification string into its
 * constituent parts.
 *
 * If the **errors points to a timelib_error_container variable, warnings
 * and errors will be recorded. You are responsible for freeing the stored
 * information with timelib_error_container_dtor(). To see whether errors have
 * occurred, inspect errors->errors_count. To see whether warnings have occurred,
 * inspect errors->warnings_count.
 */
void timelib_strtointerval(const char *s, size_t len,
                           timelib_time **begin, timelib_time **end,
                           timelib_rel_time **period, int *recurrences,
                           timelib_error_container **errors);


/* From tm2unixtime.c */

/**
 * Uses the y/m/d/h/i/s fields to calculate and store the equivalent timestamp
 * in the sse field.
 *
 * It uses the time zone information associated with 'time' to account for the
 * right UTC offset and/or DST rules. You can associate time zone information
 * with the timelib_set_timezone_* functions (see below).
 *
 * If the type is 'TIMELIB_ZONETYPE_ID' and there is no associated tzinfo, it
 * will use the second argument 'tzi' to provide the rules necessary to
 * calculate the right timestamp.
 */
void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);

/**
 * Returns the number of days from the y/m/d fields of 'time' since the Unix
 * Epoch.
 */
timelib_sll timelib_epoch_days_from_time(timelib_time *time);

/**
 * Takes the information from the y/m/d/h/i/s fields and makes sure their
 * values are in the right range.
 *
 * If a value under- or overflows it will adjust the larger measure up (or
 * down). It also takes into account leap days.
 */
void timelib_do_normalize(timelib_time *base);

/**
 * Takes the information from the y/m/d/h/i/s fields of 'rt' and makes sure
 * their values are in the right range.
 *
 * If a value under- or overflows it will adjust the larger measure up (or
 * down). As this function operates on a *relative date/time*, it also takes
 * into account leap days and correctly accounts for the difference depending
 * on the base date/time in 'base'.
 */
void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt);

/* From unixtime2tm.c */

/**
 * Takes the unix timestamp in seconds from 'ts', and calculates y, m, and d,
 * in the proleptic Gregorian calendar.
 *
 * It uses the algorithm from howardhinnant.github.io/date_algorithms.html
 */
void timelib_unixtime2date(timelib_sll ts, timelib_sll *y, timelib_sll *m, timelib_sll *d);

/**
 * Takes the unix timestamp in seconds from 'ts' and populates the y/m/d/h/i/s
 * fields of 'tm' without taking time zones into account
 */
void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts);

/**
 * Takes the Unix timestamp from 'ts', and calculates the y/m/d/h/i/s fields
 * according to the time zone information attached to 'tm'.
 */
void timelib_unixtime2local(timelib_time *tm, timelib_sll ts);

/**
 * Takes the Unix timestamp stored in 'tm', and calculates the y/m/d/h/i/s
 * fields according to the time zone information attached to 'tm'.
 */
void timelib_update_from_sse(timelib_time *tm);

/**
 * Attaches the UTC offset as time zone information to 't'.
 *
 * 'utc_offset' is in seconds East of UTC.
 */
void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset);

/**
 * Attaches the information from 'abbr_info' as time zone information to 't'.
 *
 * The timelib_abbr_info struct contains an abbreviation ('abbr') which string
 * value is duplicated, as well as a 'utc_offset' and 'dst' flag. It only
 * supports a 'dst' change over of 1 hour.
 */
void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info);

/**
 * Attaches the time zone information in 'tz' to to 't'.
 *
 * It fetches the right UTC offset that is currently stored in the time
 * stamp field in 't' ('sse'), and assigns that to the 'z' field and 'dst'
 * field (whether DST is in effect at the time). It also sets the current
 * abbreviation to the 'tz_addr' field, making sure that if a value was already
 * set it was freed.
 *
 * The time zone information in 'tz' is *not* duplicated into the 't' field so
 * it should not be freed until all timelib_time* variables have been freed as
 * well.
 */
void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);

/* From parse_tz.c */

/**
 * Returns whether the time zone ID 'timezone' is available in the time zone
 * database as pointed to be 'tzdb'.
 */
int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb);

/**
 * Converts the binary stored time zone information from 'tzdb' for the time
 * zone 'timezone' into a structure the library can use for calculations.
 *
 * The function can be used on both timelib_builtin_db as well as a time zone
 * db as opened by timelib_zoneinfo.
 *
 * 'error_code' must not be a null pointer, and will always be written to. If
 * the value is TIMELIB_ERROR_NO_ERROR then the file was parsed without
 * problems.
 *
 * The function will return null upon failure, and also set an error code
 * through 'error_code'.
 *
 * The error code is one of the TIMELIB_ERROR_* constants as listed above.
 * These error constants can be converted into a string by
 * timelib_get_error_message.
 *
 * If the function returns not-null, the 'error_code' might have a non-null
 * value that can be used to detect incompatibilities. The only one that is
 * currently detected is whether the file is a 'slim' file, in which case
 * 'error_code' will be set to TIMELIB_ERROR_SLIM_FILE.
 *
 * This function allocates memory for the new time zone structure, which must
 * be freed after use. Although it is recommended that a cache of each used
 * time zone is kept.
 */
timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code);

/**
 * Frees up the resources allocated by 'timelib_parse_tzfile'.
 */
void timelib_tzinfo_dtor(timelib_tzinfo *tz);

/**
 * Deep-clones a timelib_tzinfo structure.
 *
 * This allocates resources that need to be freed with 'timelib_tzinfo_dtor'
 */
timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);

/**
 * Returns whether DST is active with time zone 'tz' for the time stamp 'ts'.
 *
 * Returns 0 if DST is not active, 1 if DST is active, or -1 if no transitions
 * were available through 'tz'.
 */
int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);

/**
 * Returns offset information with time zone 'tz' for the time stamp 'ts'.
 *
 * The returned information contains: the offset in seconds East of UTC (in
 * 'offset'), whether DST is active ('is_dst'), what the current time zone
 * abbreviation is ('abbr') and the transition time that got to this state (in
 * 'transition_time');
 */
timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);

/**
 * Returns the UTC offset currently applicable for the information stored in 't'.
 *
 * The value returned is the UTC offset in seconds East.
 */
timelib_sll timelib_get_current_offset(timelib_time *t);

/**
 * Returns whether the timezone information in *one and *two are the same
 *
 * A timezone is considered the same if:
 * - the ->zone_type values are the same for *one and *two
 * - for TYPE_ABBR and TYPE_OFFSET, ->z + (->dst * 3600), is the same
 * - for TYPE_ID, the zone's names are the same
 */
int timelib_same_timezone(timelib_time *one, timelib_time *two);

/**
 * Displays debugging information about the time zone information in 'tz'.
 */
void timelib_dump_tzinfo(timelib_tzinfo *tz);

/**
 * Returns a pointer to the built-in time zone database.
 *
 * You must *not* free the returned pointer as it is part of the text segment.
 */
const timelib_tzdb *timelib_builtin_db(void);

/**
 * Returns a pointer to the start of an array containing a list of timezone identifiers.
 *
 * The amount of entries in the array is returned through the 'count' OUT parameter.
 *
 * Each entry contains the time zone ID ('id' field), and the position within the time zone
 * information ('pos' field). The pos field should not be used.
 */
const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count);

/* From parse_zoneinfo.c */

/**
 * Scans the directory and subdirectories of 'directory' for valid time zone files and builds
 * a time zone database out of these files.
 *
 * Typically, the directory should point to '/usr/share/zoneinfo'.
 *
 * Unlike 'timelib_builtin_db', the return value of this function must be freed
 * with the 'timelib_zoneinfo_dtor' function.
 */
timelib_tzdb *timelib_zoneinfo(const char *directory);

/**
 * Frees up the resources as created through 'timelib_zoneinfo'.
 *
 * This function must be used to free up all the resources that have been
 * allocated while calling 'timelib_zoneinfo'.
 */
void timelib_zoneinfo_dtor(timelib_tzdb *tzdb);

/* From timelib.c */

/**
 * Returns a static string containing an error message belonging to a specific
 * error code.
 */
const char *timelib_get_error_message(int error_code);

/**
 * Allocates resources for the relative time structure.
 *
 * Must be freed with 'timelib_rel_time_dtor'.
 */
timelib_rel_time* timelib_rel_time_ctor(void);

/**
 * Frees up the resources as allocated through 'timelib_rel_time_ctor'.
 */
void timelib_rel_time_dtor(timelib_rel_time* t);

/**
 * Creates a new timelib_rel_time resource and copies over the information
 * from 'tz'.
 *
 * Must be freed with 'timelib_rel_time_dtor'.
 */
timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *tz);

/**
 * Allocates resources for the time structure.
 *
 * Must be freed with 'timelib_time_dtor'.
 */
timelib_time* timelib_time_ctor(void);

/**
 * Frees up the resources as allocated through 'timelib_time_ctor'.
 */
void timelib_time_dtor(timelib_time* t);

/**
 * Creates a new timelib_time resource and copies over the information
 * from 'orig'.
 *
 * Must be freed with 'timelib_time_dtor'.
 */
timelib_time* timelib_time_clone(timelib_time* orig);

/**
 * Compares two timelib_time structures and returns which one is earlier in
 * time.
 *
 * To decide which comes earlier it uses the 'sse' (Seconds Since Epoch) and
 * 'us' (microseconds) fields.
 *
 * Returns -1 if t1 < t2, 0 if t1 == t2, and -1 if t1 > t2.
 */
int timelib_time_compare(timelib_time *t1, timelib_time *t2);

/**
 * Allocates resources for the time offset structure.
 *
 * Must be freed with 'timelib_time_offset_dtor'.
 */
timelib_time_offset* timelib_time_offset_ctor(void);

/**
 * Frees up the resources as allocated through 'timelib_time_offset_ctor'.
 */
void timelib_time_offset_dtor(timelib_time_offset* t);

/**
 * Frees up the resources allocated while converting strings to timelib_time
 * structures with the timelib_strtotime and timelib_strtointerval functions.
 */
void timelib_error_container_dtor(timelib_error_container *errors);

/**
 * Converts the 'sse' value of 'd' to a timelib_long type.
 *
 * If the value fits in the TIMELIB_LONG_MIN and TIMELIB_LONG_MAX range, the
 * value is cast to (timelib_long) and returned. If *error is not a NULL
 * pointer, it will be set to 0.
 *
 * If the value does *not* fit in the range, the function returns 0 and if
 * *error is not a NULL pointer, it will be set to 1.
 *
 * timelib_long is a 32 bit signed long integer on 32 bit platforms, and a 64
 * bit signed long long integer on 64 bit platforms. In other words, it makes
 * sure that the value in 'sse' (which is always a signed long long 64 bit
 * integer) can be used safely outside of the library.
 */
timelib_long timelib_date_to_int(timelib_time *d, int *error);

/**
 * Displays debugging information about the date/time information stored in 'd'.
 *
 * 'options' is a bit field, where:
 * - 1 controls whether the relative time portion is shown.
 * - 2 controls whether the zone type is shown.
 */
void timelib_dump_date(timelib_time *d, int options);

/**
 * Displays debugging information about the relative time information stored
 * in 'd'.
 */
void timelib_dump_rel_time(timelib_rel_time *d);

/**
 * Converts a decimal hour into hour/min/sec components
 */
void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec);

/**
 * Converts hour/min/sec values into a decimal hour
 */
void timelib_hms_to_decimal_hour(int hour, int min, int sec, double *h);

/**
 * Converts hour/min/sec/micro sec values into a decimal hour
 */
void timelib_hmsf_to_decimal_hour(int hour, int min, int sec, int us, double *h);

/**
 * Converts hour/min/sec values into seconds
 */
timelib_sll timelib_hms_to_seconds(timelib_sll h, timelib_sll m, timelib_sll s);


/* from astro.c */

/**
 * Converts the Unix Epoch time stamp 'ts' to a Julian Day
 *
 * The value returned is the number of whole days since -4714-11-24T12:00:00 UTC
 * (in the proleptic Gregorian calendar):
 * https://en.wikipedia.org/wiki/Julian_day
 */
double timelib_ts_to_julianday(timelib_sll ts);

/**
 * Converts the Unix Epoch time stamp 'ts' to the J2000 epoch
 *
 * The value returned is the number of whole days since 2000-01-01T12:00:00
 * UTC: https://en.wikipedia.org/wiki/Epoch_(astronomy)#Julian_years_and_J2000
 */
double timelib_ts_to_j2000(timelib_sll ts);

/**
 * Calculates when the Sun is above a certain latitude.
 *
 * Parameters:
 * - time: A timelib_time time describing that needs to specific midnight for a
 *         specific day.
 * - lon: The longitude of the observer (East positive, West negative).
 * - lat: The latitude of the observer (North positive, South negative).
 * - altit: The altitude. Set to -35/60 for rise/set, -6 for civil twilight,
 *          -12 for nautical, and -18 for astronomical twilight.
 * - upper_limb: set to non-zero for rise/set calculations, and 0 for twilight
 *               calculations.
 *
 * Out Parameters:
 * - h_rise: The decimal hour when the Sun rises
 * - h_set: The decimal hour when the Sun sets
 * - ts_rise: The Unix timestamp of the Sun rising
 * - ts_set: The Unix timestamp of the Sun setting
 * - ts_transit: The Unix timestmap of the Sun transitting through South
 *
 * Return Values:
 * - 0: The Sun rises and sets.
 * - +1: The Sun is always above the horizon. (ts_rise is set to ts_transit -
 *       (12 * 3600); ts_set is set to ts_transit + (12 * 3600).
 * - -1: The Sun is awlays below the horizon. (ts_rise and ts_set are set
 *       to ts_transit)
 */
int timelib_astro_rise_set_altitude(timelib_time *time, double lon, double lat, double altit, int upper_limb, double *h_rise, double *h_set, timelib_sll *ts_rise, timelib_sll *ts_set, timelib_sll *ts_transit);

/* from interval.c */

/**
 * Calculates the difference between two times
 *
 * The result is a timelib_rel_time structure that describes how you can
 * convert from 'one' to 'two' with 'timelib_add'. This does *not* necessarily
 * mean that you can go from 'two' to 'one' by using 'timelib_sub' due to the
 * way months and days are calculated.
 */
timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);

/**
 * Calculates the difference in full days between two times
 *
 * The result is the number of full days between 'one' and 'two'. It does take
 * into account 23 and 25 hour (and variants) days when the zone_type
 * is TIMELIB_ZONETYPE_ID and have the same TZID for 'one' and 'two'.
 */
int timelib_diff_days(timelib_time *one, timelib_time *two);

/**
 * Adds the relative time information 'interval' to the base time 't'.
 *
 * This can be a relative time as created by 'timelib_diff', but also by more
 * complex statements such as "next workday".
 */
timelib_time *timelib_add(timelib_time *t, timelib_rel_time *interval);
timelib_time *timelib_add_wall(timelib_time *t, timelib_rel_time *interval);

/**
 * Subtracts the relative time information 'interval' to the base time 't'.
 *
 * This can be a relative time as created by 'timelib_diff'. Unlike with
 * 'timelib_add', this does not support more complex statements such as "next
 * workday".
 */
timelib_time *timelib_sub(timelib_time *t, timelib_rel_time *interval);
timelib_time *timelib_sub_wall(timelib_time *t, timelib_rel_time *interval);

/* from parse_posix.c */

void timelib_posix_str_dtor(timelib_posix_str *ps);

timelib_posix_str* timelib_parse_posix_str(const char *posix);

/**
 * Calculate the two yearly to/from DST
 */
void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions);


#ifdef __cplusplus
} /* extern "C" */
#endif

#endif