7

I want to compare the current local time to a constant time range, but my current solution seems more difficult than I'd expect.

I can construct a chrono::DateTime<Local> with Local::now(). I can then laboriously find out if now lies in a particular time range like so:

let current_hour = now.hour();
let current_minute = now.minute();

// see if `now` lies between 06:00 and 23:00
current_hour >= 6 && current_hour < 23

// note the inelegance of the syntax and the potential for fencepost errors

If I want to check the range from 06:12–23:15, the problem becomes much worse because I have to check if the hour is equal to 6 and then if the minutes are greater than 12 and then check — zzzzz...

That's boring. I can try string representations with parse_from_rfc2822, but then I have to first emit the current date and then edit in the time of day and then check for parsing errors and now I'm sleeping again.

I imagine I'm just reading the chrono documentation wrong. If I were to implement the library, I would try to build a TimeOfDay<Local> datatype which implements Ord, thereby allowing idiomatic range checking. I figure it's already there somewhere and I'm just missing it.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Matthew Piziak
  • 3,430
  • 4
  • 35
  • 49
  • Related: https://stackoverflow.com/questions/71876855/idiomatic-way-to-check-if-a-chronodatetimeutc-is-within-date-and-time-range – Code4R7 Jul 25 '22 at 10:37

1 Answers1

7

DateTime objects have a function called time(), which returns a NaiveTime object representing the time of day. NaiveTime implements PartialOrd, and has a factory function from_hms(hour, min, sec). Using from_hms, you can create an upper bound and lower bound NaiveTime, and then compare using standard operators.

let low = NaiveTime::from_hms(6, 12, 0);
let high = NaiveTime::from_hms(23, 15, 0);
let time_of_day = Local::now().time();

if (time_of_day > low) && (time_of_day < high) {
    // do stuff...
} else {
    // do something else...
};

Playground link for completeness.

MutantOctopus
  • 3,431
  • 4
  • 22
  • 31
  • And when [issue 32311](https://github.com/rust-lang/rust/issues/32311) is completed, it will be even prettier. – Shepmaster Feb 18 '18 at 00:09
  • @Shepmaster - I suppose you mean there'll be a `TimeRange` struct with a `.contains` method for this kind of problem? – MutantOctopus Feb 18 '18 at 00:17
  • 2
    I mean that [you'll be able to replace your method with the existing `Range` struct](https://play.rust-lang.org/?gist=cc7c00d1bbba2d82fd9c3159bdee632f&version=nightly). That's the beauty of generics and composability ;-). – Shepmaster Feb 18 '18 at 00:36