Change names of parsing functions for consistency with "chrono".
All tests pass.
This commit is contained in:
parent
203b455569
commit
3566c3a793
|
@ -234,6 +234,9 @@ pub mod datetime;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
|
|
||||||
/// Parsing functions for date/time strings.
|
/// Parsing functions for date/time strings.
|
||||||
|
///
|
||||||
|
/// Parsing functions are provided for RFC 2822 ("Tue, 20 Jan 2015 17:35:20 -0800")
|
||||||
|
/// and RFC3339/ISO8601 ("2015-01-20T17:35:20.001-0800") date/time strings.
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
|
|
||||||
/// The day of week (DOW).
|
/// The day of week (DOW).
|
||||||
|
|
51
src/parse.rs
51
src/parse.rs
|
@ -1,4 +1,3 @@
|
||||||
#![allow(unstable)]
|
|
||||||
extern crate regex_macros; // for compile-time regular expression compilation
|
extern crate regex_macros; // for compile-time regular expression compilation
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
use std::num::Int;
|
use std::num::Int;
|
||||||
|
@ -88,10 +87,9 @@ use ::{Offset};
|
||||||
// naive date/time, not a time zone aware one. This returns a time zone aware
|
// naive date/time, not a time zone aware one. This returns a time zone aware
|
||||||
// date/time object in all cases.
|
// date/time object in all cases.
|
||||||
//
|
//
|
||||||
// offsetmins -- time zone offset in minutes, from string
|
|
||||||
//
|
|
||||||
// Allowed input per RFC2822 above - numeric offset or named time zone
|
|
||||||
//
|
//
|
||||||
|
/// Time zone offset in minutes, from string.
|
||||||
|
/// Allowed input per RFC2822 above - numeric offset or named time zone
|
||||||
fn offsetmins(s: &str) -> Option<i32> {
|
fn offsetmins(s: &str) -> Option<i32> {
|
||||||
let offsetre = regex!(r"^([+-])(\d\d)(\d\d)$"); // +0800 as 8 hour offset
|
let offsetre = regex!(r"^([+-])(\d\d)(\d\d)$"); // +0800 as 8 hour offset
|
||||||
let offsetmatches = offsetre.captures(s); // match time zone
|
let offsetmatches = offsetre.captures(s); // match time zone
|
||||||
|
@ -116,18 +114,15 @@ fn offsetmins(s: &str) -> Option<i32> {
|
||||||
"CST"|"MDT" => Some(-6*60),
|
"CST"|"MDT" => Some(-6*60),
|
||||||
"MST"|"PDT" => Some(-7*60),
|
"MST"|"PDT" => Some(-7*60),
|
||||||
"PST" => Some(-8*60),
|
"PST" => Some(-8*60),
|
||||||
_ => match s.len() { 1 => Some(0), _ => None } // obsolete single-letter miltary forms are treated as 0 per RFC
|
_ => match s.len() { 1 => Some(0), _ => None } // obsolete single-letter miltary forms are treated as 0 per RFC2822
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/// Makes a new `DateTime` with offset given a valid RFC2822 string.
|
||||||
// parserfc2822datetime -- parse a date/time in RFC822 format.
|
|
||||||
//
|
|
||||||
/// Makes a new `DateTime` with offset given a valid RFC822 string.
|
|
||||||
/// Example: "Tue, 20 Jan 2015 17:35:20 -0800"
|
/// Example: "Tue, 20 Jan 2015 17:35:20 -0800"
|
||||||
pub fn parserfc2822datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
pub fn rfc2822_to_datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
||||||
|
|
||||||
// Match the date format. Case-insensitive, compile-time regex.
|
// Match the date format. Case-insensitive, compile-time regex.
|
||||||
let datere = regex!(r"^(?i)(?:Mon,|Tue,|Wed,|Thu,|Fri,|Sat,|Sun,)??\s*(\d+)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d\d\d\d)\s+(\d+):(\d+):(\d+)\s*([+-]\d\d\d\d|[A-Z]+)$");
|
let datere = regex!(r"^(?i)(?:Mon,|Tue,|Wed,|Thu,|Fri,|Sat,|Sun,)??\s*(\d+)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d\d\d\d)\s+(\d+):(\d+):(\d+)\s*([+-]\d\d\d\d|[A-Z]+)$");
|
||||||
|
@ -171,12 +166,10 @@ pub fn parserfc2822datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
||||||
_ => return None // date conversion failed
|
_ => return None // date conversion failed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// fmtrfc2822datetime -- format DateTime as RFC 2822 date.
|
|
||||||
//
|
|
||||||
/// Formats a DateTime as an RF2822 string.
|
/// Formats a DateTime as an RF2822 string.
|
||||||
/// This is primarily for debugging.
|
/// This is primarily for debugging.
|
||||||
pub fn fmtrfc2822datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
pub fn fmt_rfc2822_datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
||||||
dt.format("%a, %e %b %Y %H:%M:%S %z").to_string() // inverse of parsing
|
dt.format("%a, %e %b %Y %H:%M:%S %z").to_string() // inverse of parsing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,12 +210,10 @@ pub fn fmtrfc2822datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
||||||
// readability, to specify a full-date and full-time separated by
|
// readability, to specify a full-date and full-time separated by
|
||||||
// (say) a space character.
|
// (say) a space character.
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// parserfc3339datetime -- parse a date/time in RFC822 format.
|
|
||||||
//
|
|
||||||
/// Parse a string with a RFC3339 date, time, and offset into a DateTime.
|
/// Parse a string with a RFC3339 date, time, and offset into a DateTime.
|
||||||
/// This is the subset of ISO 8601 date and time strings most used on the Web.
|
/// This is the subset of ISO 8601 date and time strings most used on the Web.
|
||||||
pub fn parserfc3339datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
pub fn rfc3339_to_datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
||||||
let datere = regex!(r"^(?i)(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d+)??([+-]\d\d\d\d|[A-Z]+)$"); // format regex
|
let datere = regex!(r"^(?i)(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d+)??([+-]\d\d\d\d|[A-Z]+)$"); // format regex
|
||||||
let matches = datere.captures(s.trim()); // Pattern match the date
|
let matches = datere.captures(s.trim()); // Pattern match the date
|
||||||
let captures = match matches {
|
let captures = match matches {
|
||||||
|
@ -253,11 +244,9 @@ pub fn parserfc3339datetime(s: &str) -> Option<::DateTime<::FixedOffset>> {
|
||||||
_ => return None // date conversion failed
|
_ => return None // date conversion failed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// parsensfract -- parse ".NNN" into nanoseconds
|
/// Parse ".NNN" into nanoseconds.
|
||||||
//
|
/// Assumes input has already been checked for ".NNN" format.
|
||||||
// Assumes format is ".NNN" for any number of digits
|
|
||||||
//
|
|
||||||
fn parsensfract(s: &str) -> u32 {
|
fn parsensfract(s: &str) -> u32 {
|
||||||
let sdigits = &s[1..]; // trim off leading "."
|
let sdigits = &s[1..]; // trim off leading "."
|
||||||
let sdigits9 = &sdigits[0..(cmp::min(sdigits.len(),9))]; // truncate at 9 digits after "."
|
let sdigits9 = &sdigits[0..(cmp::min(sdigits.len(),9))]; // truncate at 9 digits after "."
|
||||||
|
@ -268,9 +257,9 @@ fn parsensfract(s: &str) -> u32 {
|
||||||
v*scale // as nanoseconds
|
v*scale // as nanoseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats a DateTime as an RFC 3339 date, with 9 digits of nanoseconds.
|
/// Formats a DateTime as an RFC 3339/ISO8601 date, with 9 digits of nanoseconds.
|
||||||
/// This is primarily for debugging use.
|
/// This is the inverse operation of rfc3339 parsing.
|
||||||
pub fn fmtrfc3339datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
pub fn fmt_rfc3339_datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
||||||
dt.format("%Y-%m-%dT%H:%M:%S.%f%z").to_string() // inverse of parsing
|
dt.format("%Y-%m-%dT%H:%M:%S.%f%z").to_string() // inverse of parsing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +268,7 @@ pub fn fmtrfc3339datetime(dt: ::DateTime<::FixedOffset>) -> String {
|
||||||
// Unit tests
|
// Unit tests
|
||||||
//
|
//
|
||||||
#[test]
|
#[test]
|
||||||
|
/// Test RFC2822 parser.
|
||||||
fn testrfc2822parser() {
|
fn testrfc2822parser() {
|
||||||
// Test data - [input, expected result after parse and format]
|
// Test data - [input, expected result after parse and format]
|
||||||
let testdates = [
|
let testdates = [
|
||||||
|
@ -299,19 +289,20 @@ fn testrfc2822parser() {
|
||||||
for testdate in testdates.iter() {
|
for testdate in testdates.iter() {
|
||||||
let date = testdate[0]; // input
|
let date = testdate[0]; // input
|
||||||
let checkdate = testdate[1]; // expected result or ""
|
let checkdate = testdate[1]; // expected result or ""
|
||||||
let d = parserfc2822datetime(date); // parse a date
|
let d = rfc2822_to_datetime(date); // parse a date
|
||||||
let dt = match d { // did we get a value?
|
let dt = match d { // did we get a value?
|
||||||
Some(dt) => dt, // yes, go on
|
Some(dt) => dt, // yes, go on
|
||||||
None => if checkdate != "" { panic!("Failed to convert date {}", date)} else { continue },
|
None => if checkdate != "" { panic!("Failed to convert date {}", date)} else { continue },
|
||||||
};
|
};
|
||||||
// let mut s = String::new();
|
// let mut s = String::new();
|
||||||
let s = fmtrfc2822datetime(dt); // convert date/time back to string
|
let s = fmt_rfc2822_datetime(dt); // convert date/time back to string
|
||||||
if s != checkdate { // check for expected result
|
if s != checkdate { // check for expected result
|
||||||
panic!("Date conversion failed for {}\nReceived: {}\nExpected: {}",date, s, checkdate);
|
panic!("Date conversion failed for {}\nReceived: {}\nExpected: {}",date, s, checkdate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
/// Test RFC3339/ISO8601 parser.
|
||||||
fn testrfc3339parser() {
|
fn testrfc3339parser() {
|
||||||
// Test data - [input, expected result after parse and format]
|
// Test data - [input, expected result after parse and format]
|
||||||
let testdates = [
|
let testdates = [
|
||||||
|
@ -332,13 +323,13 @@ fn testrfc3339parser() {
|
||||||
for testdate in testdates.iter() {
|
for testdate in testdates.iter() {
|
||||||
let date = testdate[0]; // input
|
let date = testdate[0]; // input
|
||||||
let checkdate = testdate[1]; // expected result or ""
|
let checkdate = testdate[1]; // expected result or ""
|
||||||
let d = parserfc3339datetime(date); // parse a date
|
let d = rfc3339_to_datetime(date); // parse a date
|
||||||
let dt = match d { // did we get a value?
|
let dt = match d { // did we get a value?
|
||||||
Some(dt) => dt, // yes, go on
|
Some(dt) => dt, // yes, go on
|
||||||
None => if checkdate != "" { panic!("Failed to convert date {}", date)} else { continue },
|
None => if checkdate != "" { panic!("Failed to convert date {}", date)} else { continue },
|
||||||
};
|
};
|
||||||
// let mut s = String::new();
|
// let mut s = String::new();
|
||||||
let s = fmtrfc3339datetime(dt); // convert date/time back to string
|
let s = fmt_rfc3339_datetime(dt); // convert date/time back to string
|
||||||
if s != checkdate { // check for expected result
|
if s != checkdate { // check for expected result
|
||||||
panic!("Date conversion failed for {}\nReceived: {}\nExpected: {}",date, s, checkdate);
|
panic!("Date conversion failed for {}\nReceived: {}\nExpected: {}",date, s, checkdate);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue