Changeset 2792
- Timestamp:
- Dec 31, 2011 9:01:59 PM (17 months ago)
- File:
-
- 1 edited
-
ofw/fs/unixtime.fth (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ofw/fs/unixtime.fth
r752 r2792 3 3 4 4 decimal 5 \ date&time is number of seconds since 1970 5 \ February is given 29 days so the loop in >d/m will exit at the "unloop". 6 \ The array begins at March so that the leap day falls at the end. 6 7 create days/month 7 \ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec8 31 c, 28 c, 31 c, 30 c, 31 c, 30 c, 31 c, 31 c, 30 c, 31 c, 30 c, 31c,8 \ Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb 9 31 c, 30 c, 31 c, 30 c, 31 c, 31 c, 30 c, 31 c, 30 c, 31 c, 31 c, 29 c, 9 10 10 : >d/m ( day-in-year -- day month ) 11 12 0 do 12 days/month i ca+ c@ 2dup < if 13 drop 1+ i 1+ leave 14 then 15 - 16 loop 11 \ In >d/m and d/m>, the yearly period starts on March 1. day-in-year is 12 \ relative to March 1, and month-index 0 is March, 9 is December, 10 is January, 13 \ 11 is February. This representation simplifies the calculations by 14 \ putting the optional leap day at the end, i.e. day-of-year=365. 15 16 \ Convert day-in-year to day-of-month and month-index. 17 18 : >d/m ( day-in-year0..365 -- day1..31 month-index0..11 ) 19 d# 12 0 do ( days-left ) 20 days/month i ca+ c@ 2dup < if ( days-left ) 21 drop 1+ i unloop exit ( -- day1..31 month-index0..11 ) 22 then ( days-left ) 23 - ( days-left' ) 24 loop ( days-left ) 25 \ This is reached only if the argument is >365 26 1+ d# 12 ( day1..31 month-index0..11 ) 17 27 ; 18 : unix-seconds> ( seconds -- s m h d m y ) 19 60 u/mod 60 u/mod 24 u/mod ( s m h days ) 20 [ 365 4 * 1+ ] literal /mod >r ( s m h day-in-cycle ) ( r: cycles ) 21 dup [ 365 365 + 31 + 29 + ] literal 22 2dup = if \ exactly leap year Feb 29 23 3drop 2 29 2 ( s m h year-in-cycle d m ) 24 else 25 > if 1- then \ after leap year 26 365 u/mod ( s m h day-in-year year-in-cycle ) 27 swap >d/m ( s m h year-in-cycle d m ) 28 then 29 rot r> 4 * + 1970 + ( s m h d m y ) 28 29 \ Convert day-of-month and month-index to day-in-year. 30 31 : d/m> ( day1..31 month-index0..11 -- day-in-year0..365 ) 32 swap 1- swap 0 ?do i days/month + c@ + loop ( day-in-year ) 30 33 ; 31 : >unix-seconds ( s m h d m y -- seconds ) \ since 1970 32 d# 1970 - 4 /mod [ d# 365 4 * 1+ ] literal * ( s m h d m yrs days ) 33 swap d# 365 * + ( s m h d m days ) 34 swap 1 max d# 12 min ( s m h d days m' ) 35 1- 0 ?do i days/month + c@ + loop ( s m h d days ) 36 + 1- ( s m h days ) 37 d# 24 * + d# 60 * + d# 60 * + 34 35 \ 36 d# 365 constant d/y 37 d/y d# 30 * \ Years from 1970 to 2000 38 d# 7 + \ Leap days from 1970 to 2000 39 d# 31 + \ Days in January 2000 40 d# 28 + \ Days in February 2000 (not a leap year) 41 constant days-to-break 42 43 : unix-seconds> ( seconds -- s m h d m y ) 44 \ Changing the 3 /mod's below to u/mod's would "fix" the year 2038 problem 45 \ at the expense of breaking dates before 1970. 46 d# 60 /mod d# 60 /mod d# 24 /mod ( s m h days ) 47 48 \ Rotate the number space so that day 0 is March 1, 2000 49 \ That's convenient because it begins a 4 year + 1 day leap cycle 50 days-to-break - 51 52 \ Adjust days before day 0 for the fact that 2000, unlike other 53 \ 0mod4 years, is not a leap year 54 dup 0< if 1- then ( s m h days' ) 55 56 \ Reduce modulo the number of days in a 4-year leap cycle 57 \ This depends on floored division 58 [ d/y 4 * 1+ ] literal /mod >r ( s m h day-in-cycle r: cycles ) 59 60 \ Reduce by the number of days in a normal year 61 d/y /mod ( s m h day-in-year year-in-cycle r: cycles ) 62 63 \ If year-in-cycle is 4, it's Feb 29 64 dup 4 = if ( s m h day-in-year year-in-cycle r: cycles ) 65 \ Leap day Feb 29 at end of cycle 66 swap d/y + swap 1- ( s m h day-in-year' year-in-cycle' r: cycles ) 67 then ( s m h day-in-year year-in-cycle r: cycles ) 68 r> 4 * + >r ( s m h day-in-year r: year ) 69 70 >d/m ( s m h day-in-month month-index r: year ) 71 72 \ Adjust the month number - at this point March is 0 and we want it to be 3 73 3 + ( s m h d month' r: year ) 74 75 \ Months 13 and 14 are January and February of the following year 76 dup d# 13 >= if ( s m h d month r: year ) 77 d# 12 - r> 1+ >r ( s m h d month' r: year' ) 78 then ( s m h d month r: year ) 79 80 r> d# 2000 + ( s m h d m y ) 81 ; 82 83 : >unix-seconds ( s m h d m y -- seconds ) \ since 1970 84 d# 2000 - >r ( s m h d m r: y' ) 85 86 \ Move January and February to the end so the leap day is day number 365 87 dup 3 < if ( s m h d month' r: y ) 88 d# 12 + r> 1- >r ( s m h d month' r: y' ) 89 then ( s m h d month r: y ) 90 91 \ Convert month numbers 3..14 to 0..11 92 3 - ( s m h d month-index r: y ) 93 94 \ Convert day and month to day in year 95 d/m> ( s m h day-in-year r: y ) 96 97 r@ 4 / ( s m h day-in-year leap-years r: y ) 98 r> d/y * + ( s m h day-in-year year-days ) 99 + ( s m h days ) 100 101 \ Adjust for the missing leap day in 2000 102 dup 0< if 1+ then ( s m h days' ) 103 104 \ Adjust to 1970 105 days-to-break + ( s m h days' ) 106 107 108 \ Changing the 3 *'s below to u*'s would "fix" the year 2038 problem 109 \ at the expense of breaking dates before 1970. 110 d# 24 * + d# 60 * + d# 60 * + ( seconds ) 38 111 ; 39 112
Note: See TracChangeset
for help on using the changeset viewer.
