How do I convert a chrono `DateTime<Local>` instance to `DateTime<Utc>`? - time

There is a question asked before for the conversion in the other way(Utc -> Local)
I am trying to convert Local datetime into Utc time:
use chrono::{Local, UTC, TimeZone};
let utc = chrono::UTC::now(); // 2019-07-04 15:13:19.014970700
let local = chrono::Local::now(); // 2019-07-04 17:13:19.014970700 +03:00
I am currently expecting some API like local.to_utc(). Maybe I can implement a TryFrom trait for such conversion.
How can I convert Local datetime to Utc datetime?

As of chrono 0.4.7, this is now taken care of in a much cleaner way:
use chrono::prelude::*;
fn main() {
let utc = Utc::now();
let local = Local::now();
let converted: DateTime<Utc> = DateTime::from(local);
println!("{}\n{}", utc, converted);
}
This gives an output of:
2019-07-30 18:19:27.176827 UTC
2019-07-30 18:19:27.176836 UTC

Chrono provides the TimeZone trait which has the method from_local_datetime.
use chrono::prelude::*;
fn main() {
let local = Local::now();
let utc = Utc
.from_local_datetime(&local.naive_local())
.single()
.unwrap();
dbg!(local.naive_local());
dbg!(utc);
}
On my local machine it gives me:
[src/main.rs:10] local.naive_local() = 2019-07-04T14:25:15.093909965
[src/main.rs:11] utc = 2019-07-04T12:25:15.093909965Z

You can use chrono::DateTime::with_timezone to convert any DateTime to another time zone.
It works for structs that implements TimeZone:
chrono::Local, chrono::Utc. and chrono_tz::Tz.
Example:
#![forbid(unsafe_code)]
use chrono::{DateTime, Local, Utc};
fn main() {
let local_now: DateTime<Local> = Local::now();
let utc_now: DateTime<Utc> = local_now.with_timezone(&Utc);
println!("local = {}", local_now);
println!("utc = {}", utc_now);
}
$ cargo run --bin example
local = 2021-07-01 15:45:26.251802 -07:00
utc = 2021-07-01 22:45:26.251802 UTC

Related

How to convert millisecond (uint64) into Time Format RFC3999 with millisecond (string) in GO

How do i convert millisecond (uint64) into Time Format RFC3999 with millisecond (string) in GO?
For example:
var milleSecond int64
milleSecond = 1645286399999 //My Local Time : Sat Feb 19 2022 23:59:59
var loc = time.FixedZone("UTC-4", -4*3600)
string1 := time.UnixMilli(end).In(loc).Format(time.RFC3339)
Actual Result: 2022-02-19T11:59:59-04:00
Expected Result(should be): 2022-02-19T11:59:59.999-04:00
You are asking for an RFC3339 formatted string, with seconds reported to the nearest millisecond. There's no format string in the time package for this (only with whole seconds and nanosecond accuracy), but you can make your own.
Here's the string for seconds to the nearest nanosecond, copied from the standard library:
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
You can make a millisecond version of this easily enough by removing the .999999999 (report time to the nearest nanosecond, removing trailing zeros) to .000 (report time to the nearest millisecond, don't remove trailing zeros). This format is documented under time.Layout in the package docs https://pkg.go.dev/time#pkg-constants:
RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"
Code (playground link):
package main
import (
"fmt"
"time"
)
const RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"
func main() {
ms := int64(1645286399999) //My Local Time : Sat Feb 19 2022 23:59:59
var loc = time.FixedZone("UTC-4", -4*3600)
fmt.Println(time.UnixMilli(ms).In(loc).Format(RFC3339Milli))
}
Output:
2022-02-19T11:59:59.999-04:00

How To Find Time Difference using Chrono library in Rust

I have a Rust program where I want to do some simple benchmarking with start time and end time!
use chrono::{NaiveTime, Utc};
fn main() {
let start_time: NaiveTime = Utc::now().time();
let end_time: NaiveTime = Utc::now().time();
println!("Total time taken to run is {}", end_time - start_time);
}
The code above prints as:
Total time taken to run is PT520.532696S
I guess it is 520 seconds if I'm not wrong, but how can I convert that into minutes? Is there a better way?
A simple look to the doc give the answer:
use chrono::Utc;
fn main() {
let start_time = Utc::now().time();
let end_time = Utc::now().time();
let diff = end_time - start_time;
println!("Total time taken to run is {}", diff.num_minutes());
}
but be aware that it's not a good way to mesure time in a monotonic way, this code could show -5 minutes if user change the system date somehow. Also call time() remove the information of the date, and this is strange when you use chrono because generally you don't want to ignore the date so just remove time() call.
It seems the accepted answer has some potential flaws.
A potentially better way as recommended in the rust nursery
is the following:
use std::time::{Duration, Instant};
use std::thread;
fn expensive_function() {
thread::sleep(Duration::from_secs(1));
}
fn main() {
let start = Instant::now();
expensive_function();
let duration = start.elapsed();
println!("Time elapsed in expensive_function() is: {:?}", duration);
}

How to format SystemTime to string?

It seems there is no way I can turn SystemTime into a string. I have to use SystemTime because I need the value returned from std::fs::Metadata::created().
You should use Chrono for its formatting support. Since Chrono v0.4.0 this is much easier, as it now implements direct conversions from std::time::SystemTime:
extern crate chrono;
use chrono::offset::Utc;
use chrono::DateTime;
use std::time::SystemTime;
let system_time = SystemTime::now();
let datetime: DateTime<Utc> = system_time.into();
println!("{}", datetime.format("%d/%m/%Y %T"));
If you wanted the time in local timezone instead of UTC, use Local instead of Utc.
For the full list of formatting specifiers see the Chrono documentation.
The time crate is now a viable alternative to chrono. See the format() method for details on returning a String from an OffsetDateTime. Also make sure to check the strftime specifiers table when making your formatting string.
use time::OffsetDateTime;
use std::time::SystemTime;
fn systemtime_strftime<T>(dt: T, format: &str) -> String
where T: Into<OffsetDateTime>
{
dt.into().format(format)
}
fn main() {
let st = SystemTime::now();
println!("{}", systemtime_strftime(st, "%d/%m/%Y %T"));
}
Play

How to convert Unix time / time since the epoch to standard date and time?

I'm using the chrono crate; after some digging I discovered the DateTime type has a function timestamp() which could generate epoch time of type i64. However, I couldn't find out how to convert it back to DateTime.
extern crate chrono;
use chrono::*;
fn main() {
let date = chrono::UTC.ymd(2020, 1, 1).and_hms(0, 0, 0);
println!("{}", start_date.timestamp());
// ...how to convert it back?
}
You first need to create a NaiveDateTime and then use it to create a DateTime again:
extern crate chrono;
use chrono::prelude::*;
fn main() {
let datetime = Utc.ymd(2020, 1, 1).and_hms(0, 0, 0);
let timestamp = datetime.timestamp();
let naive_datetime = NaiveDateTime::from_timestamp(timestamp, 0);
let datetime_again: DateTime<Utc> = DateTime::from_utc(naive_datetime, Utc);
println!("{}", datetime_again);
}
Playground
Not sure if I'm missing something, or chrono expanded its feature set in the meantime, but its 2021 and at least since chrono 0.4.0 there appears to be a cleaner way to do it:
https://docs.rs/chrono/0.4.19/chrono/#conversion-from-and-to-epoch-timestamps
use chrono::{DateTime, TimeZone, Utc};
// Construct a datetime from epoch:
let dt = Utc.timestamp(1_500_000_000, 0);
assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000");
// Get epoch value from a datetime:
let dt = DateTime::parse_from_rfc2822("Fri, 14 Jul 2017 02:40:00 +0000").unwrap();
assert_eq!(dt.timestamp(), 1_500_000_000);
So your full conversion should look like this:
extern crate chrono;
use chrono::*;
fn main() {
let start_date = chrono::Utc.ymd(2020, 1, 1).and_hms(0, 0, 0);
let ts = start_date.timestamp();
println!("{}", &ts);
let end_date = Utc.timestamp(ts, 0);
assert_eq!(end_date, start_date);
}
You can use the parse_duration crate: https://docs.rs/parse_duration/2.1.0/parse_duration/
extern crate parse_duration;
use parse_duration::parse;
use std::time::Duration;
fn main() {
// 1587971749 seconds since UNIX_EPOCH
assert_eq!(parse("1587971749"), Ok(Duration::new(1587971749, 0)));
// One hour less than a day
assert_eq!(parse("1 day -1 hour"), Ok(Duration::new(82_800, 0)));
// Using exponents
assert_eq!(
parse("1.26e-1 days"),
Ok(Duration::new(10_886, 400_000_000))
);
// Extra things will be ignored
assert_eq!(
parse("Duration: 1 hour, 15 minutes and 29 seconds"),
Ok(Duration::new(4529, 0))
);
}

Windows SYSTEMTIME structure different then System clock?

The goal of the following code is to call the Win32 function FileTimeToSystemTime:
pub fn convert_times(s: SystemTime) -> Option<SYSTEMTIME> {
let mut st = SYSTEMTIME::default();
let x: u64 = unsafe { transmute(s) };
let low = (x & 0x00000000FFFFFFFF) as u32;
let high = ((x & 0xFFFFFFFF00000000) >> 32) as u32;
let fs = FILETIME {
dwLowDateTime: low,
dwHighDateTime: high,
};
if unsafe { FileTimeToSystemTime(transmute(&fs), transmute(&mut st)) } > 0 {
Some(st)
} else {
None
}
}
When I take a known file time 131147233180069965 which was generated at 2016-08-03T14:41 US-EST(GMT+5) according to my computer's clock. The return structure I get from this returns 2016-0803T18:41:58.006
This is +4 hours.
While US-EST is GMT+5?
Is it because Daylight Saving Time is -1hr?
FileTimeToLocalFileTime() returns time at UTC. In the United States, locations normally in EST transition to EDT during Daylight Saving Time, so it will be GMT+5 DST-1 or UTC-4.
To get time in the local timezone and take DST into account, one would instead need to call SystemTimeToTzSpecificLocalTime().
Generally this inadvisable as working in UTC is preferable for computers as 2 intercommunicating computers are not necessarily in the same timezone.

Resources