How to get Timestamp of the current Date and time in Rust - datetime

I simply want to retrieve the current Time and Date and store it in a variable.
For this, I tried to use the chrono::DateTime.
In the documentation I found this:
use chrono::{DateTime, TimeZone, NaiveDateTime, Utc};
let dt = DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11), Utc);
This lets me store a specific Date and Time but I couldn't figure out how to retrieve the actual current date and time and put it in my DateTime-Variable.

Use rust, use it now:
use chrono;
fn main() {
println!("{:?}", chrono::offset::Local::now());
println!("{:?}", chrono::offset::Utc::now());
}

To answer the question in the title of how to get the current timestamp:
use chrono::Utc;
let dt = Utc::now();
let timestamp: i64 = dt.timestamp();
println!("Current timestamp is {}", timestamp);

Standart Rust timestamp method:
use std::time::SystemTime;
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis(); // See struct std::time::Duration methods
println!("{}", now);

Related

How can I display chrono DateTime without fractional seconds?

If I print the current time directly, it includes many trailing decimals:
println!("{:?}", chrono::offset::Utc::now());
2022-12-01T07:56:54.242352517Z
How can I get it to print like this?
2022-12-01T07:56:54Z
You can use to_rfc3339_opts. It accepts arguments for the format of the seconds and if the Z should be present.
let time = chrono::offset::Utc::now();
let formatted = time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
println!("{:?}", time); // 2022-12-01T08:32:20.580242150Z
println!("{}", formatted); // 2022-12-01T08:32:20Z
Rust Playground

How do I update the year in a chrono DateTime instance?

How do I change the year in a DateTime<FixedOffset> instance (from the rust crate chrono)?
That is, create a new instance of DateTime<FixedOffset> that copies the month and day from the old instance.
In other words, how would I complete the following code:
fn datetime_set_year(
datetime: &DateTime<FixedOffset>,
year: &i32
) -> DateTime<FixedOffset>
The code can ignore exceptional cases like leap days (if that is possible).
The passed DateTime<FixedOffset> instance is taken apart to a Date<FixedOffset> instance and a NaiveTime instance. Then FixedOffset.ymd and .and_time create a new DateTime<FixedOffset> instance using the passed year.
Rust Playground
fn datetime_with_year(datetime: &DateTime<FixedOffset>, year: i32) -> DateTime<FixedOffset> {
let date: Date<FixedOffset> = datetime.date();
let time: NaiveTime = datetime.time();
let fixedoffset: &FixedOffset = datetime.offset();
match fixedoffset.ymd(year, date.month(), date.day()).and_time(time) {
Some(datetime_) => {
eprintln!("fixedoffset.ymd() Some {:?}", datetime_);
datetime_
}
None => {
eprintln!("fixedoffset.ymd() None");
datetime.clone()
}
}
}
Update: or use datetime.with_year(year) as recommended by #Jmb.
Doh! 😑

Chrono DateTime from u64 unix timestamp in Rust

How does one convert a u64 unix timestamp into a DateTime<Utc>?
let timestamp_u64 = 1657113606;
let date_time = ...
There are many options.
Assuming we want a chrono::DateTime. The offset page suggests:
Using the TimeZone methods on the UTC struct is the preferred way to construct DateTime instances.
There is a TimeZone method timestamp_millis_opt we can use.
use chrono::{TimeZone, Utc};
let timestamp_i64 = 1657113606;
let date_time = Utc.timestamp_millis_opt(timestamp_i64).unwrap();
Another option uses the appropriately named from_timestamp_millis method, but needs more code to do it if you want DateTime instead of NaiveDateTime.
use chrono::{DateTime, NaiveDateTime, Utc};
let timestamp_i64 = 1657113606;
let naive_date_time = NaiveDateTime::from_timestamp_millis(timestamp_i64).unwrap();
let date_time = DateTime::<Utc>::from_utc(naive_date_time, Utc);

How do I convert a vector of strings to a vector of integers in a functional way?

I'm trying to convert Vec<&str> to Vec<u16> but I can't figure out a functional way to do it.
let foo: &str = "1,2,3"; // Parsing a string here
let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's
I need to get bar into a Vec<u16>.
There's an iterator adapter map! You'd use it like this:
let bar: Vec<u16> = foo.split(",").map(|x| x.parse::<u16>().unwrap()).collect();
parse is a library function that relies on the trait FromStr, and it can return an error, so we need to unwrap() the error type. (This is a good idea for a short example, but in real code, you will want to handle the error properly - if you have a value that's not a u16 there, your program will just crash).
map takes a closure that takes it's parameter by value and then returns the iterator obtained by lazily applying that function. You're collecting all of the values here, but if you only take(5) of them, you would only parse 5 of the strings.
You haven't fully specified your problem. Specifically, what should happen when one of the strings cannot be parsed into a number? When you parse a number from a string using parse, it can fail. That is why the function returns a Result:
fn parse<F>(&self) -> Result<F, F::Err>
where
F: FromStr,
Here's a solution that takes the vector, gets an iterator with iter, changes each item using map and ultimately returns a Result using collect. If the parsing was a success, you get an Ok. If any failed, you get an Err:
fn main() {
let input = "1,2,3";
let strings: Vec<_> = input.split(",").collect();
let numbers: Result<Vec<u16>, _> = strings.iter().map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
Or you could remove failed conversions by filtering out Err values with flat_map:
fn main() {
let input = "1,2,3";
let strings: Vec<_> = input.split(",").collect();
let numbers: Vec<u16> = strings.iter().flat_map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
Of course, it's a bit silly to convert the string into a vector of strings and then convert it again to a vector of integers. If you actually have a comma-separated string and want numbers, do it in one go:
fn main() {
let input = "1,2,3";
let numbers: Result<Vec<u16>, _> = input.split(",").map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
See also:
Why does `Option` support `IntoIterator`?
My take as someone not really experienced in Rust yet.
fn main() {
let foo: &str = "1,2,3"; // Parsing a string here
let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's
// here the magic happens
let baz = bar.iter().map(|x| x.parse::<i64>());
for x in baz {
match x {
Ok(i) => println!("{}", i),
Err(_) => println!("parse failed"),
}
}
}
Note that since parse returns a Result, you have to extract the value from each parsed element. You might want to behave in a different way, e.g. filter only the succeeded results.

How do I convert a chrono `DateTime<UTC>` instance to `DateTime<Local>`?

My goal is to convert utc into loc:
use chrono::{Local, UTC, TimeZone};
let utc = chrono::UTC::now();
let loc = chrono::Local::now();
println!("{:?}", utc);
println!("{:?}", loc);
println!("{:?}", utc.with_timezone(&Local));
println!("{:?}", Local.from_utc_datetime(&utc.naive_local()));
... which produced the following output:
2015-02-26T16:22:27.873593Z
2015-02-26T17:22:27.873663+01:00
2015-02-26T15:22:27.873593+00:00
2015-02-26T15:22:27.873593+00:00
The loc time shown in the second row is what I want to see when converting utc.
How do I properly convert a DateTime<UTC> instance to DateTime<Local>?
Meta
I am using chrono 0.2.2. In the DateTime.from_utc method it's even telling me I should use the TimeZone trait. However, I am missing something.
Starting with chrono 0.4.7 you can convert them between with using from trait in a simpler way:
use chrono::prelude::*;
fn main() {
let utc = Utc::now();
let local = Local::now();
let converted: DateTime<Local> = DateTime::from(utc);
}
Oops, thank you for reporting. This is a bug and registered as the issue #26. This should be fixed in Chrono 0.2.3.
Besides from the bug, utc.with_timezone(&Local) is indeed a correct way to convert to the local time. There is an important identity that utc.with_timezone(&Local).with_timezone(&UTC) should be equal to utc (except for the exceptional case, where the local time zone has been changed).

Resources