How can I display chrono DateTime without fractional seconds? - datetime

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

Related

`foo.Seconds()` (type time.Duration) error - Cannot use 'd.Step.Seconds()' (type float64) as type time.Duration

I'm still really new to go...so,
The crux of my issue can be summed up as this: I'm preparing data to be sent off to a remote API which requires this field to be a time.Duration type, which I was trying to send as a string type of seconds ###s and would time.ParseDuration() it to seconds, however that was a mistake.
type Duration struct {
Duration time.Duration
Step time.Duration
}
// Needs to return a structure containing a duration formatted
// item and an item which is strictly in `seconds` format IE
// `int` or `float` `+` `"s"`.
func getDuration(pr *PromRequest) (Duration, error) {
duration, err := time.ParseDuration(pr.TimeRange)
if err != nil {
return Duration{}, nil
}
timeValue, err := strconv.Atoi(pr.TimeRange[:len(pr.TimeRange)-1])
if err != nil {
return Duration{}, err
}
// convert day value to day in hours
step := time.Duration(int64(24*timeValue) * 60 / 14)
return Duration{
Duration: duration,
Step: step, // <-- should be a time.Duration type...
}, nil
}
// \/\/hatever
func getMetricsWithRange(pr *PromRequest) (model.Value, error) {
d, err := getDuration(pr)
if err != nil {
e := fmt.Errorf("unable to translate received time into proper parsed time signature: %s", err)
fmt.Println(e)
return nil, err
}
...
r := v1.Range{
Start: time.Now().Add(-d.Duration),
End: time.Now(),
Step: d.Step.Seconds(), // <-- error lands here stating it's a float64
}
...
}
** EDIT **
So I think I understand my misunderstanding now. time.Duration() returns a time.Duration type on which one can then send through .Seconds(), which returns a float64.
In the caller, which consumed the returned struct, when I printed the value of the instance variable it would be something NOT time.Duration. I needed it to be in seconds as a time.Duration type in the form of ###s, which I learned time.Duration won't do. Calling .Seconds() on it failed with the error Cannot use 'd.Step.Seconds()' (type float64) as type time.Duration
OK, so my misunderstanding came from a few factors. One: I was really tired. Two: I'm new to go and statically typed languages in general. Three: I believed I needed to send v1.Range.Step in seconds, which was wrong. I took a look at the receiving code which transforms the time.Duration value into seconds itself.
Now, the bigger part of this problem came from the fact that my frontend code was sending a value in days using the letter d in the string. time.ParseDuration() doesn't handle d days so instead of using days I thought I would simply pass a time value in seconds.
Turns out, the easiest way to fix this was to simply send seconds from the frontend. I was never able to get the go code to work right.
Duration.Seconds() returns a float64 value, because the duration value may not be a whole second and it may have decimal digits to represent the exact duration. If the Step variable is to be a duration rounded up to the nearest second, use Duration.Round(time.Second):
...
Step: Step.Round(time.Second)
This will give you a duration that is rounded to a whole second.
If you want to get the seconds value, that's not a duration, that's simply an integer:
...
Step: int(Step.Seconds())
However, in this case the resulting Step is not a duration, but simply an int value giving the number of seconds.

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

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

How can I round a chrono::Datetime to the nearest second?

I want to get the current time rounded to the nearest second using the chrono crate but I don't know how to strip or round the result of
chrono::UTC.now().
It doesn't seem like there are any operations to modify an existing `DateTime.
chrono::UTC.now()
Returns: 2019-05-22T20:07:59.250194427Z
I want to get: 2019-05-22T20:07:59.000000000Z
How would I go about doing that in the most efficient way without breaking up the DateTime value into its components and recreating it?
Use the round_subsecs method with 0 as an argument.
use chrono::prelude::*;
fn main() {
let utc: DateTime<Utc> = Utc::now().round_subsecs(0);
println!("{}", utc);
}
The result is:
2019-05-22 20:50:46 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