tzinfo: adding parsers for timezone files.
parent
4dca0e6651
commit
73f2fac980
|
@ -0,0 +1 @@
|
|||
John Benediktsson
|
|
@ -0,0 +1 @@
|
|||
Parsing timezone files.
|
|
@ -0,0 +1,107 @@
|
|||
USING: accessors alien.c-types alien.data alien.endian arrays
|
||||
assocs calendar classes.struct combinators hashtables io
|
||||
io.binary io.encodings.binary io.files kernel locals math
|
||||
math.order sequences strings ;
|
||||
|
||||
IN: tzinfo
|
||||
|
||||
<PRIVATE
|
||||
|
||||
STRUCT: tzhead
|
||||
{ tzh_magic char[4] }
|
||||
{ tzh_reserved char[16] }
|
||||
{ tzh_ttisgmtcnt be32 }
|
||||
{ tzh_ttisstdcnt be32 }
|
||||
{ tzh_leapcnt be32 }
|
||||
{ tzh_timecnt be32 }
|
||||
{ tzh_typecnt be32 }
|
||||
{ tzh_charcnt be32 } ;
|
||||
|
||||
PACKED-STRUCT: ttinfo
|
||||
{ tt_gmtoff be32 }
|
||||
{ tt_isdst uchar }
|
||||
{ tt_abbrind uchar } ;
|
||||
|
||||
ERROR: bad-magic ;
|
||||
|
||||
: check-magic ( header -- header )
|
||||
dup tzh_magic>> "TZif" sequence= [ bad-magic ] unless ;
|
||||
|
||||
TUPLE: tzfile header transition-times local-times types abbrevs
|
||||
leaps is-std is-gmt ;
|
||||
|
||||
C: <tzfile> tzfile
|
||||
|
||||
: read-be32 ( -- n )
|
||||
4 read be32 deref ;
|
||||
|
||||
: read-tzfile ( -- tzfile )
|
||||
tzhead read-struct check-magic dup {
|
||||
[ tzh_timecnt>> [ read-be32 ] replicate ]
|
||||
[ tzh_timecnt>> [ read1 ] replicate ]
|
||||
[ tzh_typecnt>> [ ttinfo read-struct ] replicate ]
|
||||
[ tzh_charcnt>> read ]
|
||||
[ tzh_leapcnt>> [ read-be32 read-be32 2array ] replicate ]
|
||||
[ tzh_ttisstdcnt>> read ]
|
||||
[ tzh_ttisgmtcnt>> read ]
|
||||
} cleave <tzfile> ;
|
||||
|
||||
:: tznames ( abbrevs -- assoc )
|
||||
0 [
|
||||
0 over abbrevs index-from dup
|
||||
] [
|
||||
[ dupd abbrevs subseq >string 2array ] keep 1 + swap
|
||||
] produce 2nip >hashtable ;
|
||||
|
||||
TUPLE: local-time gmt-offset dst? abbrev std? gmt? ;
|
||||
|
||||
C: <local-time> local-time
|
||||
|
||||
TUPLE: transition seconds timestamp local-time ;
|
||||
|
||||
C: <transition> transition
|
||||
|
||||
:: tzfile>transitions ( tzfile -- transitions )
|
||||
tzfile abbrevs>> tznames :> abbrevs
|
||||
tzfile is-std>> :> is-std
|
||||
tzfile is-gmt>> :> is-gmt
|
||||
tzfile types>> [
|
||||
[
|
||||
{
|
||||
[ tt_gmtoff>> seconds ]
|
||||
[ tt_isdst>> 1 = ]
|
||||
[ tt_abbrind>> abbrevs at ]
|
||||
} cleave
|
||||
] dip
|
||||
[ is-std ?nth dup [ 1 = ] when ]
|
||||
[ is-gmt ?nth dup [ 1 = ] when ] bi <local-time>
|
||||
] map-index :> local-times
|
||||
tzfile transition-times>>
|
||||
tzfile local-times>> [
|
||||
[ dup unix-time>timestamp ] [ local-times nth ] bi*
|
||||
<transition>
|
||||
] 2map ;
|
||||
|
||||
TUPLE: tzinfo tzfile transitions ;
|
||||
|
||||
C: <tzinfo> tzinfo
|
||||
|
||||
: find-transition ( timestamp tzinfo -- transition )
|
||||
[ timestamp>unix-time ] [ transitions>> ] bi*
|
||||
[ [ seconds>> before? ] with find drop ]
|
||||
[ swap [ 1 [-] swap nth ] [ last ] if* ] bi ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: file>tzinfo ( path -- tzinfo )
|
||||
binary [
|
||||
read-tzfile dup tzfile>transitions <tzinfo>
|
||||
] with-file-reader ;
|
||||
|
||||
: from-utc ( timestamp tzinfo -- timestamp' )
|
||||
[ drop instant >>gmt-offset ]
|
||||
[ find-transition local-time>> gmt-offset>> ] 2bi
|
||||
convert-timezone ;
|
||||
|
||||
: normalize ( timestamp tzinfo -- timestamp' )
|
||||
[ instant convert-timezone ] [ from-utc ] bi* ;
|
Loading…
Reference in New Issue