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

痴心易碎 提交于 2020-06-22 22:51:28

问题


I am parsing dates and times in Rust using the chrono crate. The dates and times are from a website in which the date and time are from different sections of the page.

The date is shown in the format %d/%m/%Y (example: 27/08/2018). The time is shown with only the hour (example: 12, 10, 21, etc.)

I want to store these datetimes as UTC so that I can compute time remaining until a given datetime from now in a "timezone agnostic" way. I know which timezone these datetimes are from (Paris time).

I created a NaiveDate from the date input (this is a work in progress so there's no error handling yet):

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

From that point on, what would be the best way to get the UTC DateTime, given that I have a string with the hour?

I am lost in the various TimeZone/Offset traits, and do not know if I should use a Local, or FixedOffset and then convert to Utc.


回答1:


The Chrono documentation could probably be improved to make it easier to find how to do these things.

Assuming this is your starting point:

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);

You can then use the FixedOffset to construct a DateTime:

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

If you need to convert it to a DateTime<Utc>, you can do this:

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



回答2:


I've discovered chrono-tz and found it much easier to use. For example:

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)
}



回答3:


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

Here's an example of how you can incrementally parse multiple values from distinct strings, provide default values for unparsed information, and use Chrono's built-in timezone conversion.

The key is to use the parse function to update a Parsed struct. You can use the StrftimeItems iterator to continue to use more readable format strings.

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)
}


来源:https://stackoverflow.com/questions/50312999/how-do-i-go-from-a-naivedate-to-a-specific-timezone-with-chrono

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!