@@ -728,270 +728,6 @@ addToLibrary({
728
728
return newDate ;
729
729
} ,
730
730
731
- strptime__deps : [ '$isLeapYear' , '$arraySum' , '$addDays' , '$MONTH_DAYS_REGULAR' , '$MONTH_DAYS_LEAP' ,
732
- '$jstoi_q' , '$intArrayFromString' ] ,
733
- strptime : ( buf , format , tm ) => {
734
- // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
735
- // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html
736
- var pattern = UTF8ToString ( format ) ;
737
-
738
- // escape special characters
739
- // TODO: not sure we really need to escape all of these in JS regexps
740
- var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.' ;
741
- for ( var i = 0 , ii = SPECIAL_CHARS . length ; i < ii ; ++ i ) {
742
- pattern = pattern . replace ( new RegExp ( '\\' + SPECIAL_CHARS [ i ] , 'g' ) , '\\' + SPECIAL_CHARS [ i ] ) ;
743
- }
744
-
745
- // reduce number of matchers
746
- var EQUIVALENT_MATCHERS = {
747
- 'A' : '%a' ,
748
- 'B' : '%b' ,
749
- 'c' : '%a %b %d %H:%M:%S %Y' ,
750
- 'D' : '%m\\/%d\\/%y' ,
751
- 'e' : '%d' ,
752
- 'F' : '%Y-%m-%d' ,
753
- 'h' : '%b' ,
754
- 'R' : '%H\\:%M' ,
755
- 'r' : '%I\\:%M\\:%S\\s%p' ,
756
- 'T' : '%H\\:%M\\:%S' ,
757
- 'x' : '%m\\/%d\\/(?:%y|%Y)' ,
758
- 'X' : '%H\\:%M\\:%S'
759
- } ;
760
- // TODO: take care of locale
761
-
762
- var DATE_PATTERNS = {
763
- /* weekday name */ 'a' : '(?:Sun(?:day)?)|(?:Mon(?:day)?)|(?:Tue(?:sday)?)|(?:Wed(?:nesday)?)|(?:Thu(?:rsday)?)|(?:Fri(?:day)?)|(?:Sat(?:urday)?)' ,
764
- /* month name */ 'b' : '(?:Jan(?:uary)?)|(?:Feb(?:ruary)?)|(?:Mar(?:ch)?)|(?:Apr(?:il)?)|May|(?:Jun(?:e)?)|(?:Jul(?:y)?)|(?:Aug(?:ust)?)|(?:Sep(?:tember)?)|(?:Oct(?:ober)?)|(?:Nov(?:ember)?)|(?:Dec(?:ember)?)' ,
765
- /* century */ 'C' : '\\d\\d' ,
766
- /* day of month */ 'd' : '0[1-9]|[1-9](?!\\d)|1\\d|2\\d|30|31' ,
767
- /* hour (24hr) */ 'H' : '\\d(?!\\d)|[0,1]\\d|20|21|22|23' ,
768
- /* hour (12hr) */ 'I' : '\\d(?!\\d)|0\\d|10|11|12' ,
769
- /* day of year */ 'j' : '00[1-9]|0?[1-9](?!\\d)|0?[1-9]\\d(?!\\d)|[1,2]\\d\\d|3[0-6]\\d' ,
770
- /* month */ 'm' : '0[1-9]|[1-9](?!\\d)|10|11|12' ,
771
- /* minutes */ 'M' : '0\\d|\\d(?!\\d)|[1-5]\\d' ,
772
- /* whitespace */ 'n' : ' ' ,
773
- /* AM/PM */ 'p' : 'AM|am|PM|pm|A\\.M\\.|a\\.m\\.|P\\.M\\.|p\\.m\\.' ,
774
- /* seconds */ 'S' : '0\\d|\\d(?!\\d)|[1-5]\\d|60' ,
775
- /* week number */ 'U' : '0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53' ,
776
- /* week number */ 'W' : '0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53' ,
777
- /* weekday number */ 'w' : '[0-6]' ,
778
- /* 2-digit year */ 'y' : '\\d\\d' ,
779
- /* 4-digit year */ 'Y' : '\\d\\d\\d\\d' ,
780
- /* whitespace */ 't' : ' ' ,
781
- /* time zone */ 'z' : 'Z|(?:[\\+\\-]\\d\\d:?(?:\\d\\d)?)'
782
- } ;
783
-
784
- var MONTH_NUMBERS = { JAN : 0 , FEB : 1 , MAR : 2 , APR : 3 , MAY : 4 , JUN : 5 , JUL : 6 , AUG : 7 , SEP : 8 , OCT : 9 , NOV : 10 , DEC : 11 } ;
785
- var DAY_NUMBERS_SUN_FIRST = { SUN : 0 , MON : 1 , TUE : 2 , WED : 3 , THU : 4 , FRI : 5 , SAT : 6 } ;
786
- var DAY_NUMBERS_MON_FIRST = { MON : 0 , TUE : 1 , WED : 2 , THU : 3 , FRI : 4 , SAT : 5 , SUN : 6 } ;
787
-
788
- var capture = [ ] ;
789
- var pattern_out = pattern
790
- . replace ( / % ( .) / g, ( m , c ) => EQUIVALENT_MATCHERS [ c ] || m )
791
- . replace ( / % ( .) / g, ( _ , c ) => {
792
- let pat = DATE_PATTERNS [ c ] ;
793
- if ( pat ) {
794
- capture . push ( c ) ;
795
- return `(${ pat } )` ;
796
- } else {
797
- return c ;
798
- }
799
- } )
800
- . replace ( // any number of space or tab characters match zero or more spaces
801
- / \s + / g, '\\s*'
802
- ) ;
803
-
804
- var matches = new RegExp ( '^' + pattern_out , "i" ) . exec ( UTF8ToString ( buf ) )
805
-
806
- function initDate ( ) {
807
- function fixup ( value , min , max ) {
808
- return ( typeof value != 'number' || isNaN ( value ) ) ? min : ( value >= min ? ( value <= max ? value : max ) : min ) ;
809
- } ;
810
- return {
811
- year : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_year , 'i32' ) } } } + 1900 , 1970 , 9999 ) ,
812
- month : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_mon , 'i32' ) } } } , 0 , 11 ) ,
813
- day : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_mday , 'i32' ) } } } , 1 , 31 ) ,
814
- hour : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_hour , 'i32' ) } } } , 0 , 23 ) ,
815
- min : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_min , 'i32' ) } } } , 0 , 59 ) ,
816
- sec : fixup ( { { { makeGetValue ( 'tm' , C_STRUCTS . tm . tm_sec , 'i32' ) } } } , 0 , 59 ) ,
817
- gmtoff : 0
818
- } ;
819
- } ;
820
-
821
- if ( matches ) {
822
- var date = initDate ( ) ;
823
- var value ;
824
-
825
- var getMatch = ( symbol ) = > {
826
- var pos = capture . indexOf ( symbol ) ;
827
- // check if symbol appears in regexp
828
- if ( pos >= 0 ) {
829
- // return matched value or null (falsy!) for non-matches
830
- return matches [ pos + 1 ] ;
831
- }
832
- return ;
833
- } ;
834
-
835
- // seconds
836
- if ( ( value = getMatch ( 'S' ) ) ) {
837
- date . sec = jstoi_q ( value ) ;
838
- }
839
-
840
- // minutes
841
- if ( ( value = getMatch ( 'M' ) ) ) {
842
- date . min = jstoi_q ( value ) ;
843
- }
844
-
845
- // hours
846
- if ( ( value = getMatch ( 'H' ) ) ) {
847
- // 24h clock
848
- date . hour = jstoi_q ( value ) ;
849
- } else if ( ( value = getMatch ( 'I' ) ) ) {
850
- // AM/PM clock
851
- var hour = jstoi_q ( value ) ;
852
- if ( ( value = getMatch ( 'p' ) ) ) {
853
- hour += value . toUpperCase ( ) [ 0 ] === 'P' ? 12 : 0 ;
854
- }
855
- date . hour = hour ;
856
- }
857
-
858
- // year
859
- if ( ( value = getMatch ( 'Y' ) ) ) {
860
- // parse from four-digit year
861
- date . year = jstoi_q ( value ) ;
862
- } else if ( ( value = getMatch ( 'y' ) ) ) {
863
- // parse from two-digit year...
864
- var year = jstoi_q ( value ) ;
865
- if ( ( value = getMatch ( 'C' ) ) ) {
866
- // ...and century
867
- year += jstoi_q ( value ) * 100 ;
868
- } else {
869
- // ...and rule-of-thumb
870
- year += year < 69 ? 2000 : 1900 ;
871
- }
872
- date . year = year ;
873
- }
874
-
875
- // month
876
- if ( ( value = getMatch ( 'm' ) ) ) {
877
- // parse from month number
878
- date . month = jstoi_q ( value ) - 1 ;
879
- } else if ( ( value = getMatch ( 'b' ) ) ) {
880
- // parse from month name
881
- date . month = MONTH_NUMBERS [ value . substring ( 0 , 3 ) . toUpperCase ( ) ] || 0 ;
882
- // TODO: derive month from day in year+year, week number+day of week+year
883
- }
884
-
885
- // day
886
- if ( ( value = getMatch ( 'd' ) ) ) {
887
- // get day of month directly
888
- date . day = jstoi_q ( value ) ;
889
- } else if ( ( value = getMatch ( 'j' ) ) ) {
890
- // get day of month from day of year ...
891
- var day = jstoi_q ( value ) ;
892
- var leapYear = isLeapYear ( date . year ) ;
893
- for ( var month = 0 ; month < 12 ; ++ month ) {
894
- var daysUntilMonth = arraySum ( leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR , month - 1 ) ;
895
- if ( day <= daysUntilMonth + ( leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR ) [ month ] ) {
896
- date . day = day - daysUntilMonth ;
897
- }
898
- }
899
- } else if ( ( value = getMatch ( 'a' ) ) ) {
900
- // get day of month from weekday ...
901
- var weekDay = value . substring ( 0 , 3 ) . toUpperCase ( ) ;
902
- if ( ( value = getMatch ( 'U' ) ) ) {
903
- // ... and week number (Sunday being first day of week)
904
- // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
905
- // All days in a new year preceding the first Sunday are considered to be in week 0.
906
- var weekDayNumber = DAY_NUMBERS_SUN_FIRST [ weekDay ] ;
907
- var weekNumber = jstoi_q ( value ) ;
908
-
909
- // January 1st
910
- var janFirst = new Date ( date . year , 0 , 1 ) ;
911
- var endDate ;
912
- if ( janFirst . getDay ( ) === 0 ) {
913
- // Jan 1st is a Sunday, and, hence in the 1st CW
914
- endDate = addDays ( janFirst , weekDayNumber + 7 * ( weekNumber - 1 ) ) ;
915
- } else {
916
- // Jan 1st is not a Sunday, and, hence still in the 0th CW
917
- endDate = addDays ( janFirst , 7 - janFirst . getDay ( ) + weekDayNumber + 7 * ( weekNumber - 1 ) ) ;
918
- }
919
- date . day = endDate . getDate ( ) ;
920
- date . month = endDate . getMonth ( ) ;
921
- } else if ( ( value = getMatch ( 'W' ) ) ) {
922
- // ... and week number (Monday being first day of week)
923
- // Week number of the year (Monday as the first day of the week) as a decimal number [00,53].
924
- // All days in a new year preceding the first Monday are considered to be in week 0.
925
- var weekDayNumber = DAY_NUMBERS_MON_FIRST [ weekDay ] ;
926
- var weekNumber = jstoi_q ( value ) ;
927
-
928
- // January 1st
929
- var janFirst = new Date ( date . year , 0 , 1 ) ;
930
- var endDate ;
931
- if ( janFirst . getDay ( ) === 1 ) {
932
- // Jan 1st is a Monday, and, hence in the 1st CW
933
- endDate = addDays ( janFirst , weekDayNumber + 7 * ( weekNumber - 1 ) ) ;
934
- } else {
935
- // Jan 1st is not a Monday, and, hence still in the 0th CW
936
- endDate = addDays ( janFirst , 7 - janFirst . getDay ( ) + 1 + weekDayNumber + 7 * ( weekNumber - 1 ) ) ;
937
- }
938
-
939
- date . day = endDate . getDate ( ) ;
940
- date . month = endDate . getMonth ( ) ;
941
- }
942
- }
943
-
944
- // time zone
945
- if ( ( value = getMatch ( 'z' ) ) ) {
946
- // GMT offset as either 'Z' or +-HH:MM or +-HH or +-HHMM
947
- if ( value . toLowerCase ( ) === 'z' ) {
948
- date . gmtoff = 0 ;
949
- } else {
950
- var match = value . match ( / ^ ( (?: \- | \+ ) \d \d ) : ? ( \d \d ) ? / ) ;
951
- date . gmtoff = match [ 1 ] * 3600 ;
952
- if ( match [ 2 ] ) {
953
- date . gmtoff += date . gmtoff > 0 ? match [ 2 ] * 60 : - match [ 2 ] * 60
954
- }
955
- }
956
- }
957
-
958
- /*
959
- tm_sec int seconds after the minute 0-61*
960
- tm_min int minutes after the hour 0-59
961
- tm_hour int hours since midnight 0-23
962
- tm_mday int day of the month 1-31
963
- tm_mon int months since January 0-11
964
- tm_year int years since 1900
965
- tm_wday int days since Sunday 0-6
966
- tm_yday int days since January 1 0-365
967
- tm_isdst int Daylight Saving Time flag
968
- tm_gmtoff long offset from GMT (seconds)
969
- */
970
-
971
- var fullDate = new Date ( date . year , date . month , date . day , date . hour , date . min , date . sec , 0 ) ;
972
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_sec , 'fullDate.getSeconds()' , 'i32' ) } } } ;
973
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_min , 'fullDate.getMinutes()' , 'i32' ) } } } ;
974
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_hour , 'fullDate.getHours()' , 'i32' ) } } } ;
975
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_mday , 'fullDate.getDate()' , 'i32' ) } } } ;
976
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_mon , 'fullDate.getMonth()' , 'i32' ) } } } ;
977
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_year , 'fullDate.getFullYear()-1900' , 'i32' ) } } } ;
978
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_wday , 'fullDate.getDay()' , 'i32' ) } } } ;
979
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_yday , 'arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1' , 'i32' ) } } } ;
980
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_isdst , '0' , 'i32' ) } } } ;
981
- { { { makeSetValue ( 'tm' , C_STRUCTS . tm . tm_gmtoff , 'date.gmtoff' , LONG_TYPE ) } } } ;
982
-
983
- // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F
984
- // TODO: not sure that intArrayFromString handles all unicode characters correctly
985
- return buf + intArrayFromString ( matches [ 0 ] ) . length - 1 ;
986
- }
987
-
988
- return 0 ;
989
- } ,
990
- strptime_l__deps : [ 'strptime' ] ,
991
- strptime_l : ( buf , format , tm , locale ) => {
992
- return _strptime ( buf , format , tm ) ; // no locale support yet
993
- } ,
994
-
995
731
// ==========================================================================
996
732
// setjmp.h
997
733
// ==========================================================================
0 commit comments