Consider the following input to a program:
- time =
18:00
- timezone =
Europe/London
(or any sensible representation of a timezone, possible examples includeEurope__London
,Europe.London
, etc ... see note) - the date, which can be obtained by stripping out the date fields from
chrono::Utc::now()
.
Is it possible to combine these data, or something similar, into a chrono::Datetime
object?
Note: that the particular form of the string is not particularly important, and can be changed. This data just comes from a text file.
I think there may be two possible approaches.
- Construct a string representation in rfc3339 format using
format!
, then parse this using the datetimeparse_from_rfc3339
function. This seems like the wrong approach - creating bigger strings and then parsing them feels like an inefficient or "clumsy" approach. But it seems relatively easy to do. - The second option I am less confident on. I would guess there is a way to operate on some chrono types directly to create a datetime from each of these 3 pieces. But as for this option, I am somewhat lost and have no real idea how to approach the problem this way.
My attempts so far:
Option 1: Process strings
A chrono::DateTime
object can be constructed using a string in rfc3339 format. Here is how that might be done:
let datetime_rfc3339_format_string =
format!("{}T{}-{}",
date_string, time_string, timezone_string);
let datetime_remote = chrono::DateTime::parse_from_rfc3339(datetime_remote_rfc3339_format);
The question then becomes how to build those three components in String format.
Timezone String
I previously managed to come up with a way of constructing a chrono_tz::Tz
object from a string. See the following linked question.
let chrono_timezone = Tz::from_str(timezone.as_str())
.expect("failed to convert string to chrono tz");
This works, assuming a string in the format of something like:
Europe/London
But in order to use something in rfc3339 format, we need to convert this "timezone name" into an "offset in number of hours". That depends both on the global datelines as well as local rules for things such as daylight savings.
So here I become stuck. I don't know how to convert a Tz
object into an offset in numbers of hours, which in principle would depend on the current date.
Date String
This part is relatively easy. We can build a DateTime object from Utc::now()
and extract the date using date_naive()
. This can then be formatted as a String.
let datetime = chrono::Utc::now();
let date = datetime.date_naive();
let string_date = format!("{}", date);
Time String
I already have these in the required (String) format. For example, I can read these from a text file, and they are in the format of, for example:
08:00
Option 2:
Since I already have a timezone object, my thoughts were that it might be possible to use this to construct a DateTime object directly. It seems like the FixedOffset
type has a with_ymd_and_hms
function.
This suggests that somehow DateTime objects can be constructed from Timezone objects with this additional information, which I have access to.
But, this is where I get stuck. I do not know how to proceed here, or even if FixedOffset
is the type I want to be working with. I don't know how it is related to Tz
, if at all.
let chrono_timezone = Tz::from_str(timezone.as_str())
.expect("failed to convert string to chrono tz");