Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 808
Justmaker Avatar asked May 13 '18 05:05

Justmaker


People also ask

How to convert naivedatetime to local datetime?

Using DateTime<Local>::from () doesn't work either. Neither structs have methods to convert from a NaiveDateTime, and NaiveDateTime doesn't have methods to convert into Local. Yet, we can do things like this: someLocalDateTime.date ().and_time (some_naive_time). So why can't we just do Local::new (some_naive_date_time)?

Do I need to use exact time zones in my application?

If you need to use exact time zones in your application, it’s important to keep them up to date. Let’s say, for example, that you want to send an email or notification to all users at a certain point in time in their respective time zone.

How do I get the timezone of a saved date?

To fetch all saved dates, users can use the GET /fetch/$timezone endpoint, where $timezone might be something like UTC, GMT, Africa/Algiers, or any of the many time zones Chrono-TZ and the IANA support. For cases such as Europe/Vienna, the caller needs to url encode the / to %2F when calling the endpoint, and we’d have to url decode it again.

Are there any countries that change their time zones?

In just the last five years, there have been time zone changes in North Korea, Russia, Haiti, Chile, and more. Some of these changes involve adding or removing daylight saving time, others are based on different factors. If you need to use exact time zones in your application, it’s important to keep them up to date.


2 Answers

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());
like image 78
Peter Hall Avatar answered Oct 15 '22 14:10

Peter Hall


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)
}
like image 33
Justmaker Avatar answered Oct 15 '22 13:10

Justmaker