MCPcopy Create free account
hub / github.com/apache/arrow-rs / string_to_datetime

Function string_to_datetime

arrow-cast/src/parse.rs:176–228  ·  view source on GitHub ↗

Accepts a string and parses it relative to the provided `timezone` In addition to RFC3339 / ISO8601 standard timestamps, it also accepts strings that use a space ` ` to separate the date and time as well as strings that have no explicit timezone offset. Examples of accepted inputs: `1997-01-31T09:26:56.123Z` # RCF3339 `1997-01-31T09:26:56.123-05:00` # RCF3339 `1997-01-31 09:26:56.123-05

(timezone: &T, s: &str)

Source from the content-addressed store, hash-verified

174///
175/// [IANA timezones]: https://www.iana.org/time-zones
176pub fn string_to_datetime<T: TimeZone>(timezone: &T, s: &str) -> Result<DateTime<T>, ArrowError> {
177 let err =
178 |ctx: &str| ArrowError::ParseError(format!("Error parsing timestamp from '{s}': {ctx}"));
179
180 let bytes = s.as_bytes();
181 if bytes.len() < 10 {
182 return Err(err("timestamp must contain at least 10 characters"));
183 }
184
185 let parser = TimestampParser::new(bytes);
186 let date = parser.date().ok_or_else(|| err("error parsing date"))?;
187 if bytes.len() == 10 {
188 let datetime = date.and_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap());
189 return timezone
190 .from_local_datetime(&datetime)
191 .single()
192 .ok_or_else(|| err("error computing timezone offset"));
193 }
194
195 if !parser.test(10, b'T') && !parser.test(10, b't') && !parser.test(10, b' ') {
196 return Err(err("invalid timestamp separator"));
197 }
198
199 let (time, mut tz_offset) = parser.time().ok_or_else(|| err("error parsing time"))?;
200 let datetime = date.and_time(time);
201
202 if tz_offset == 32 {
203 // Decimal overrun
204 while tz_offset < bytes.len() && bytes[tz_offset].is_ascii_digit() {
205 tz_offset += 1;
206 }
207 }
208
209 if bytes.len() <= tz_offset {
210 return timezone
211 .from_local_datetime(&datetime)
212 .single()
213 .ok_or_else(|| err("error computing timezone offset"));
214 }
215
216 if (bytes[tz_offset] == b'z' || bytes[tz_offset] == b'Z') && tz_offset == bytes.len() - 1 {
217 return Ok(timezone.from_utc_datetime(&datetime));
218 }
219
220 // Parse remainder of string as timezone
221 let parsed_tz: Tz = s[tz_offset..].trim_start().parse()?;
222 let parsed = parsed_tz
223 .from_local_datetime(&datetime)
224 .single()
225 .ok_or_else(|| err("error computing timezone offset"))?;
226
227 Ok(parsed.with_timezone(timezone))
228}
229
230/// Accepts a string in RFC3339 / ISO8601 standard format and some
231/// variants and converts it to a nanosecond precision timestamp.

Callers 12

test_parse_timezoneFunction · 0.85
parse_dateFunction · 0.85
parseMethod · 0.85
decodeMethod · 0.85

Calls 8

errFunction · 0.85
dateMethod · 0.80
as_bytesMethod · 0.45
lenMethod · 0.45
testMethod · 0.45
timeMethod · 0.45
parseMethod · 0.45
with_timezoneMethod · 0.45

Tested by 6

test_parse_timezoneFunction · 0.68