@@ -52,7 +52,8 @@ export class Date {
5252 hour : i32 = 0 ,
5353 min : i32 = 0 ,
5454 sec : i32 = 0 ,
55- ms : i32 = 0 ;
55+ ms : i32 = 0 ,
56+ offsetMs : i32 = 0 ;
5657
5758 let dateString = dateTimeString ;
5859 let posT = dateTimeString . indexOf ( "T" ) ;
@@ -61,37 +62,67 @@ export class Date {
6162 let timeString : string ;
6263 dateString = dateTimeString . substring ( 0 , posT ) ;
6364 timeString = dateTimeString . substring ( posT + 1 ) ;
64- // parse the HH-MM-SS component
65+
66+ // might end with an offset ("Z", "+05:30", "-08:00", etc.)
67+ for ( let i = timeString . length - 1 ; i >= 0 ; i -- ) {
68+ let c = timeString . charCodeAt ( i ) ;
69+ if ( c == 90 ) { // Z
70+ timeString = timeString . substring ( 0 , i ) ;
71+ break ;
72+ } else if ( c == 43 || c == 45 ) { // + or -
73+ if ( i == timeString . length - 1 ) {
74+ throw new RangeError ( E_INVALIDDATE ) ;
75+ }
76+
77+ let posColon = timeString . indexOf ( ":" , i + 1 ) ;
78+ if ( ~ posColon ) {
79+ let offsetHours = i32 . parse ( timeString . substring ( i + 1 , posColon ) ) ;
80+ let offsetMinutes = i32 . parse ( timeString . substring ( posColon + 1 ) ) ;
81+ offsetMs = ( offsetHours * 60 + offsetMinutes ) * MILLIS_PER_MINUTE ;
82+ } else {
83+ let offsetHours = i32 . parse ( timeString . substring ( i + 1 ) ) ;
84+ offsetMs = offsetHours * MILLIS_PER_HOUR ;
85+ }
86+
87+ if ( c == 45 ) offsetMs = - offsetMs ; // negative offset
88+ timeString = timeString . substring ( 0 , i ) ;
89+ break ;
90+ }
91+ }
92+
93+ // parse the HH:MM:SS component
6594 let timeParts = timeString . split ( ":" ) ;
6695 let len = timeParts . length ;
6796 if ( len <= 1 ) throw new RangeError ( E_INVALIDDATE ) ;
6897
69- hour = I32 . parseInt ( timeParts [ 0 ] ) ;
70- min = I32 . parseInt ( timeParts [ 1 ] ) ;
98+ hour = i32 . parse ( timeParts [ 0 ] ) ;
99+ min = i32 . parse ( timeParts [ 1 ] ) ;
71100 if ( len >= 3 ) {
72- let secAndMs = timeParts [ 2 ] ;
73- let posDot = secAndMs . indexOf ( "." ) ;
101+ let secAndFrac = timeParts [ 2 ] ;
102+ let posDot = secAndFrac . indexOf ( "." ) ;
74103 if ( ~ posDot ) {
75- // includes milliseconds
76- sec = I32 . parseInt ( secAndMs . substring ( 0 , posDot ) ) ;
77- ms = I32 . parseInt ( secAndMs . substring ( posDot + 1 ) ) ;
104+ // includes fractional seconds (truncate to milliseconds)
105+ sec = i32 . parse ( secAndFrac . substring ( 0 , posDot ) ) ;
106+ ms = i32 . parse ( secAndFrac . substr ( posDot + 1 , 3 ) . padEnd ( 3 , "0" ) ) ;
78107 } else {
79- sec = I32 . parseInt ( secAndMs ) ;
108+ sec = i32 . parse ( secAndFrac ) ;
80109 }
81110 }
82111 }
112+
83113 // parse the YYYY-MM-DD component
84114 let parts = dateString . split ( "-" ) ;
85- let year = I32 . parseInt ( parts [ 0 ] ) ;
115+ let year = i32 . parse ( parts [ 0 ] ) ;
86116 let month = 1 , day = 1 ;
87117 let len = parts . length ;
88118 if ( len >= 2 ) {
89- month = I32 . parseInt ( parts [ 1 ] ) ;
119+ month = i32 . parse ( parts [ 1 ] ) ;
90120 if ( len >= 3 ) {
91- day = I32 . parseInt ( parts [ 2 ] ) ;
121+ day = i32 . parse ( parts [ 2 ] ) ;
92122 }
93123 }
94- return new Date ( epochMillis ( year , month , day , hour , min , sec , ms ) ) ;
124+
125+ return new Date ( epochMillis ( year , month , day , hour , min , sec , ms ) - offsetMs ) ;
95126 }
96127
97128 constructor ( private epochMillis : i64 ) {
0 commit comments