关于datetime:如何使用Chrono从NaiveDate转到特定的TimeZone?

How do I go from a NaiveDate to a specific TimeZone with Chrono?

我正在使用chrono crate解析Rust中的日期和时间。 日期和时间来自网站,其中日期和时间来自页面的不同部分。

日期以%d/%m/%Y格式显示(例如:27/08/2018)。 时间仅显示小时(例如:12,10,21等)

我希望将这些日期时间存储为UTC,以便我可以计算从现在开始以"时区不可知"的方式保留给定日期时间的剩余时间。 我知道这些日期时间来自哪个时区(巴黎时间)。

我从日期输入中创建了一个NaiveDate(这是一项正在进行的工作,所以还没有错误处理):

1
let naive_date = NaiveDate::parse_from_str(date,"%d/%m/%Y").unwrap()

从那时起,获得UTC DateTime的最佳方式是什么,因为我有一个小时的字符串?

我迷失在各种TimeZone / Offset特征中,并且不知道我是否应该使用LocalFixedOffset然后转换为Utc


可能会改进Chrono文档,以便更容易找到如何执行这些操作。

假设这是你的出发点:

1
2
3
4
5
6
7
8
9
10
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};

// The date you parsed
let date = NaiveDate::from_ymd(2018, 5, 13);
// The known 1 hour time offset in seconds
let tz_offset = FixedOffset::east(1 * 3600);
// The known time
let time = NaiveTime::from_hms(17, 0, 0);
// Naive date time, with no time zone information
let datetime = NaiveDateTime::new(date, time);

然后,您可以使用FixedOffset构造DateTime

1
let dt_with_tz: DateTime<FixedOffset> = tz_offset.from_local_datetime(&datetime).unwrap();

如果需要将其转换为DateTime,则可以执行以下操作:

1
let dt_with_tz_utc: DateTime<Utc> = Utc.from_utc_datetime(&dt_with_tz.naive_utc());


我发现了chrono-tz,发现它更容易使用。 例如:

1
2
3
4
5
pub fn create_date_time_from_paris(date: NaiveDate, time: NaiveTime) -> DateTime<Utc> {
    let naive_datetime = NaiveDateTime::new(date, time);
    let paris_time = Paris.from_local_datetime(&naive_datetime).unwrap();
    paris_time.with_timezone(&Utc)
}


The dates and times are from a website in which the date and time are from different sections of the page.

下面是一个示例,说明如何逐步解析不同字符串中的多个值,为未解析的信息提供默认值,以及使用Chrono的内置时区转换。

关键是使用parse函数来更新Parsed结构。 您可以使用StrftimeItems迭代器继续使用更易读的格式字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
extern crate chrono;

use chrono::prelude::*;

fn example(date: &str, hour: &str) -> chrono::ParseResult<DateTime<Utc>> {
    use chrono::format::{self, strftime::StrftimeItems, Parsed};

    // Set up a struct to perform successive parsing into
    let mut p = Parsed::default();

    // Parse the date information
    format::parse(&mut p, date.trim(), StrftimeItems::new("%d/%m/%Y"))?;
    // Parse the time information and provide default values we don't parse
    format::parse(&mut p, hour.trim(), StrftimeItems::new("%H"))?;
    p.minute = Some(0);
    p.second = Some(0);

    // Convert parsed information into a DateTime in the Paris timezone
    let paris_time_zone_offset = FixedOffset::east(1 * 3600);
    let dt = p.to_datetime_with_timezone(&paris_time_zone_offset)?;

    // You can also use chrono-tz instead of hardcoding it
    // let dt = p.to_datetime_with_timezone(&chrono_tz::Europe::Paris)?;

    // Convert to UTC
    Ok(dt.with_timezone(&Utc))
}

fn main() {
    let date ="27/08/2018";
    let hour ="12";

    println!("dt = {:?}", example(date, hour)); // Ok(2018-08-27T11:00:00Z)
}