referrerpolicy=no-referrer-when-downgrade

sc_offchain/api/
timestamp.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Helper methods dedicated to timestamps.
20
21use sp_core::offchain::Timestamp;
22use std::time::{Duration, SystemTime};
23
24/// Returns the current time as a `Timestamp`.
25pub fn now() -> Timestamp {
26	let now = SystemTime::now();
27	let epoch_duration = now.duration_since(SystemTime::UNIX_EPOCH);
28	match epoch_duration {
29		Err(_) => {
30			// Current time is earlier than UNIX_EPOCH.
31			Timestamp::from_unix_millis(0)
32		},
33		Ok(d) => {
34			let duration = d.as_millis();
35			// Assuming overflow won't happen for a few hundred years.
36			Timestamp::from_unix_millis(
37				duration
38					.try_into()
39					.expect("epoch milliseconds won't overflow u64 for hundreds of years; qed"),
40			)
41		},
42	}
43}
44
45/// Returns how a `Timestamp` compares to "now".
46///
47/// In other words, returns `timestamp - now()`.
48pub fn timestamp_from_now(timestamp: Timestamp) -> Duration {
49	Duration::from_millis(timestamp.diff(&now()).millis())
50}
51
52/// Converts the deadline into a `Future` that resolves when the deadline is reached.
53///
54/// If `None`, returns a never-ending `Future`.
55pub fn deadline_to_future(
56	deadline: Option<Timestamp>,
57) -> futures::future::MaybeDone<impl futures::Future<Output = ()>> {
58	use futures::future::{self, Either};
59
60	future::maybe_done(match deadline.map(timestamp_from_now) {
61		None => Either::Left(future::pending()),
62		// Only apply delay if we need to wait a non-zero duration
63		Some(duration) if duration <= Duration::from_secs(0) =>
64			Either::Right(Either::Left(future::ready(()))),
65		Some(duration) => Either::Right(Either::Right(futures_timer::Delay::new(duration))),
66	})
67}