diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs
index 76672d5adbc..f73f85a0242 100644
--- a/client/tests/integration/triggers/time_trigger.rs
+++ b/client/tests/integration/triggers/time_trigger.rs
@@ -1,4 +1,4 @@
-use std::time::Duration;
+use std::time::{Duration, SystemTime};
 
 use eyre::Result;
 use iroha::{
@@ -31,14 +31,6 @@ pub fn default_consensus_estimation() -> Duration {
         .map_or_else(|| unreachable!(), |x| x)
 }
 
-fn curr_time() -> core::time::Duration {
-    use std::time::SystemTime;
-
-    SystemTime::now()
-        .duration_since(SystemTime::UNIX_EPOCH)
-        .unwrap()
-}
-
 /// Macro to abort compilation, if `e` isn't `true`
 macro_rules! const_assert {
     ($e:expr) => {
@@ -61,7 +53,7 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result
 
     let (_rt, _peer, mut test_client) = <PeerBuilder>::new().with_port(10_775).start_with_runtime();
     wait_for_genesis_committed(&vec![test_client.clone()], 0);
-    let start_time = curr_time();
+    let start_time = SystemTime::now();
 
     // Start listening BEFORE submitting any transaction not to miss any block committed event
     let event_listener = get_block_committed_event_listener(&test_client)?;
@@ -94,8 +86,12 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result
     )?;
     std::thread::sleep(default_consensus_estimation());
 
-    let finish_time = curr_time();
-    let average_count = finish_time.saturating_sub(start_time).as_millis() / PERIOD.as_millis();
+    let finish_time = SystemTime::now();
+    let average_count = finish_time
+        .duration_since(start_time)
+        .unwrap_or_else(|_| Duration::from_secs(0))
+        .as_millis()
+        / PERIOD.as_millis();
 
     let actual_value = get_asset_value(&mut test_client, asset_id);
     let expected_value = prev_value
@@ -131,7 +127,7 @@ fn mint_asset_after_3_sec() -> Result<()> {
         id: asset_id.clone(),
     })?;
 
-    let start_time = curr_time();
+    let start_time = SystemTime::now();
     // Create trigger with schedule which is in the future to the new block but within block estimation time
     let schedule = TimeSchedule::starting_at(start_time + Duration::from_secs(3));
     let instruction = Mint::asset_numeric(1_u32, asset_id.clone());
@@ -257,7 +253,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> {
     // Registering trigger
     // Offset into the future to be able to register trigger
     let offset = Duration::from_secs(10);
-    let start_time = curr_time() + offset;
+    let start_time = SystemTime::now() + offset;
     let schedule = TimeSchedule::starting_at(start_time).with_period(TRIGGER_PERIOD);
 
     let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
diff --git a/client/tests/integration/tx_history.rs b/client/tests/integration/tx_history.rs
index c10083f8712..ad29fa89689 100644
--- a/client/tests/integration/tx_history.rs
+++ b/client/tests/integration/tx_history.rs
@@ -1,4 +1,4 @@
-use std::{str::FromStr as _, thread};
+use std::{str::FromStr as _, thread, time::SystemTime};
 
 use eyre::Result;
 use iroha::{
@@ -60,7 +60,7 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()>
         .execute_all()?;
     assert_eq!(transactions.len(), 50);
 
-    let mut prev_creation_time = core::time::Duration::from_millis(0);
+    let mut prev_creation_time = SystemTime::UNIX_EPOCH;
     transactions
         .iter()
         .map(AsRef::as_ref)
diff --git a/core/src/block.rs b/core/src/block.rs
index 57cb6721f49..7de5033f010 100644
--- a/core/src/block.rs
+++ b/core/src/block.rs
@@ -159,8 +159,9 @@ mod pending {
             transactions: &[CommittedTransaction],
             consensus_estimation: Duration,
         ) -> BlockHeader {
-            let prev_block_time =
-                prev_block.map_or(Duration::ZERO, |block| block.header().creation_time());
+            let prev_block_time = prev_block.map_or(SystemTime::UNIX_EPOCH, |block| {
+                block.header().creation_time()
+            });
 
             let latest_txn_time = transactions
                 .iter()
@@ -168,9 +169,7 @@ mod pending {
                 .max()
                 .expect("INTERNAL BUG: Block empty");
 
-            let now = SystemTime::now()
-                .duration_since(SystemTime::UNIX_EPOCH)
-                .unwrap();
+            let now = SystemTime::now();
 
             // NOTE: Lower time bound must always be upheld for a valid block
             // If the clock has drifted too far this block will be rejected
@@ -200,6 +199,8 @@ mod pending {
                     .hash()
                     .expect("INTERNAL BUG: Empty block created"),
                 creation_time_ms: creation_time
+                    .duration_since(SystemTime::UNIX_EPOCH)
+                    .expect("INTERNAL BUG: Failed to get the current system time")
                     .as_millis()
                     .try_into()
                     .expect("Time should fit into u64"),
@@ -526,11 +527,9 @@ mod valid {
                 });
             }
 
-            let now = SystemTime::now()
-                .duration_since(SystemTime::UNIX_EPOCH)
-                .unwrap();
+            let now = SystemTime::now();
             let max_clock_drift = state.world().parameters().sumeragi.max_clock_drift();
-            if block.header().creation_time().saturating_sub(now) > max_clock_drift {
+            if block.header().creation_time() > now + max_clock_drift {
                 return Err(BlockValidationError::BlockInTheFuture);
             }
 
diff --git a/core/src/metrics.rs b/core/src/metrics.rs
index b377cd1986a..c95a940a154 100644
--- a/core/src/metrics.rs
+++ b/core/src/metrics.rs
@@ -114,13 +114,13 @@ impl MetricsReporter {
 
         #[allow(clippy::cast_possible_truncation)]
         if let Some(timestamp) = state_view.genesis_timestamp() {
-            let curr_time = SystemTime::now()
-                .duration_since(SystemTime::UNIX_EPOCH)
-                .unwrap();
+            let curr_time = SystemTime::now();
 
             // this will overflow in 584942417years.
             self.metrics.uptime_since_genesis_ms.set(
-                (curr_time - timestamp)
+                curr_time
+                    .duration_since(timestamp)
+                    .expect("Failed to get the current system time")
                     .as_millis()
                     .try_into()
                     .expect("Timestamp should fit into u64"),
diff --git a/core/src/queue.rs b/core/src/queue.rs
index 4b7b074c2da..6480076c23e 100644
--- a/core/src/queue.rs
+++ b/core/src/queue.rs
@@ -1,6 +1,6 @@
 //! Module with queue actor
 use core::time::Duration;
-use std::{num::NonZeroUsize, ops::Deref, sync::Arc};
+use std::{num::NonZeroUsize, ops::Deref, sync::Arc, time::SystemTime};
 
 use crossbeam_queue::ArrayQueue;
 use dashmap::{mapref::entry::Entry, DashMap};
@@ -133,8 +133,8 @@ impl Queue {
             |tx_time_to_live| core::cmp::min(self.tx_time_to_live, tx_time_to_live),
         );
 
-        let curr_time = self.time_source.get_unix_time();
-        curr_time.saturating_sub(tx_creation_time) > time_limit
+        let curr_time = SystemTime::UNIX_EPOCH + self.time_source.get_unix_time();
+        curr_time > tx_creation_time + time_limit
     }
 
     /// Returns all pending transactions.
diff --git a/core/src/state.rs b/core/src/state.rs
index d85d8c2da4c..e55f4514d11 100644
--- a/core/src/state.rs
+++ b/core/src/state.rs
@@ -1,6 +1,6 @@
 //! This module provides the [`State`] — an in-memory representation of the current blockchain state.
 use std::{
-    collections::BTreeSet, marker::PhantomData, num::NonZeroUsize, sync::Arc, time::Duration,
+    collections::BTreeSet, marker::PhantomData, num::NonZeroUsize, sync::Arc, time::SystemTime,
 };
 
 use eyre::Result;
@@ -1285,7 +1285,7 @@ pub trait StateReadOnly {
     /// Returns [`Some`] milliseconds since the genesis block was
     /// committed, or [`None`] if it wasn't.
     #[inline]
-    fn genesis_timestamp(&self) -> Option<Duration> {
+    fn genesis_timestamp(&self) -> Option<SystemTime> {
         if self.block_hashes().is_empty() {
             None
         } else {
diff --git a/core/src/tx.rs b/core/src/tx.rs
index 44fe92aed46..94875f99d09 100644
--- a/core/src/tx.rs
+++ b/core/src/tx.rs
@@ -79,10 +79,8 @@ impl AcceptedTransaction {
             }));
         }
 
-        let now = SystemTime::now()
-            .duration_since(SystemTime::UNIX_EPOCH)
-            .unwrap();
-        if tx.creation_time().saturating_sub(now) > max_clock_drift {
+        let now = SystemTime::now();
+        if tx.creation_time() > now + max_clock_drift {
             return Err(AcceptTransactionFail::TransactionInTheFuture);
         }
 
diff --git a/data_model/benches/time_event_filter.rs b/data_model/benches/time_event_filter.rs
index 7d30f09a252..fbbc890b045 100644
--- a/data_model/benches/time_event_filter.rs
+++ b/data_model/benches/time_event_filter.rs
@@ -1,6 +1,6 @@
 #![allow(missing_docs)]
 
-use std::time::Duration;
+use std::time::{Duration, SystemTime};
 
 use criterion::{criterion_group, criterion_main, Criterion};
 use iroha_data_model::prelude::*;
@@ -12,14 +12,15 @@ fn schedule_from_zero_with_little_period(criterion: &mut Criterion) {
 
     const TIMESTAMP: u64 = 1_647_443_386;
 
-    let since = Duration::from_secs(TIMESTAMP);
+    let since = SystemTime::UNIX_EPOCH + Duration::from_secs(TIMESTAMP);
     let length = Duration::from_secs(1);
     let interval = TimeInterval::new(since, length);
     let event = TimeEvent {
         prev_interval: None,
         interval,
     };
-    let schedule = TimeSchedule::starting_at(Duration::ZERO).with_period(Duration::from_millis(1));
+    let schedule =
+        TimeSchedule::starting_at(SystemTime::UNIX_EPOCH).with_period(Duration::from_millis(1));
     let filter = TimeEventFilter::new(ExecutionTime::Schedule(schedule));
 
     criterion.bench_function("count_matches_from_zero", |b| {
diff --git a/data_model/src/block.rs b/data_model/src/block.rs
index e24faa5c7d0..67c0d224e50 100644
--- a/data_model/src/block.rs
+++ b/data_model/src/block.rs
@@ -7,6 +7,8 @@
 #[cfg(not(feature = "std"))]
 use alloc::{boxed::Box, format, string::String, vec::Vec};
 use core::{fmt::Display, time::Duration};
+#[cfg(feature = "std")]
+use std::time::SystemTime;
 
 use derive_more::Display;
 use iroha_crypto::{HashOf, MerkleTree, SignatureOf};
@@ -133,8 +135,9 @@ impl BlockHeader {
     }
 
     /// Creation timestamp
-    pub const fn creation_time(&self) -> Duration {
-        Duration::from_millis(self.creation_time_ms)
+    #[cfg(feature = "std")]
+    pub fn creation_time(&self) -> SystemTime {
+        SystemTime::UNIX_EPOCH + Duration::from_millis(self.creation_time_ms)
     }
 
     /// Consensus estimation
diff --git a/data_model/src/events/time.rs b/data_model/src/events/time.rs
index e01c101b464..2d299581e07 100644
--- a/data_model/src/events/time.rs
+++ b/data_model/src/events/time.rs
@@ -1,5 +1,7 @@
 //! Time event and filter
-use core::{ops::Range, time::Duration};
+use core::time::Duration;
+#[cfg(feature = "std")]
+use std::time::SystemTime;
 
 use derive_more::Constructor;
 use getset::Getters;
@@ -173,13 +175,15 @@ impl EventFilter for TimeEventFilter {
                     //
                     // Schedule start is after current block (c1).
                     // In this case event won't match and it will be handled in the next block.
-                    let since = if Range::from(prev).contains(&schedule.start()) {
+                    let since = if prev.contains(schedule.start()) {
                         schedule.start()
                     } else {
                         prev.since() + prev.length()
                     };
                     let estimation = event.interval.since() + event.interval.length();
-                    let length = estimation - since;
+                    let length = estimation
+                        .duration_since(since)
+                        .unwrap_or_else(|_| Duration::from_secs(0));
 
                     TimeInterval::new(since, length)
                 });
@@ -204,20 +208,20 @@ impl EventFilter for TimeEventFilter {
 #[cfg(feature = "transparent_api")]
 fn count_matches_in_interval(schedule: &Schedule, interval: &TimeInterval) -> u32 {
     schedule.period().map_or_else(
-        || u32::from(Range::from(*interval).contains(&schedule.start())),
+        || u32::from(interval.contains(schedule.start())),
         |period| {
             #[allow(clippy::integer_division)]
             let k = interval
                 .since()
-                .saturating_sub(schedule.start())
+                .duration_since(schedule.start())
+                .unwrap_or_else(|_| Duration::from_secs(0))
                 .as_millis()
                 / period.as_millis();
             let start = schedule.start() + multiply_duration_by_u128(period, k);
-            let range = Range::from(*interval);
             (0..)
                 .map(|i| start + period * i)
                 .skip_while(|time| *time < interval.since())
-                .take_while(|time| range.contains(time))
+                .take_while(|time| interval.contains(*time))
                 .count()
                 .try_into()
                 .expect("Overflow. The schedule is too frequent relative to the interval length")
@@ -253,9 +257,12 @@ impl Schedule {
     /// Create new [`Schedule`] starting at `start` and without period
     #[must_use]
     #[inline]
-    pub fn starting_at(start: Duration) -> Self {
+    #[cfg(feature = "std")]
+    pub fn starting_at(start: SystemTime) -> Self {
         Self {
             start_ms: start
+                .duration_since(SystemTime::UNIX_EPOCH)
+                .expect("INTERNAL BUG: Failed to get the current system time")
                 .as_millis()
                 .try_into()
                 .expect("INTERNAL BUG: Unix timestamp exceedes u64::MAX"),
@@ -277,8 +284,9 @@ impl Schedule {
     }
 
     /// Instant of the first execution
-    pub fn start(&self) -> Duration {
-        Duration::from_millis(self.start_ms)
+    #[cfg(feature = "std")]
+    pub fn start(&self) -> SystemTime {
+        SystemTime::UNIX_EPOCH + Duration::from_millis(self.start_ms)
     }
 
     /// Period of repeated executions
@@ -289,9 +297,12 @@ impl Schedule {
 
 impl TimeInterval {
     /// Create new [`Self`]
-    pub fn new(since: Duration, length: Duration) -> Self {
+    #[cfg(feature = "std")]
+    pub fn new(since: SystemTime, length: Duration) -> Self {
         Self {
             since_ms: since
+                .duration_since(SystemTime::UNIX_EPOCH)
+                .expect("INTERNAL BUG: Failed to get the current system time")
                 .as_millis()
                 .try_into()
                 .expect("INTERNAL BUG: Unix timestamp exceedes u64::MAX"),
@@ -303,20 +314,21 @@ impl TimeInterval {
     }
 
     /// Instant of the previous execution
-    pub fn since(&self) -> Duration {
-        Duration::from_millis(self.since_ms)
+    #[cfg(feature = "std")]
+    pub fn since(&self) -> SystemTime {
+        SystemTime::UNIX_EPOCH + Duration::from_millis(self.since_ms)
     }
 
     /// Time since the previous execution
     pub fn length(&self) -> Duration {
         Duration::from_millis(self.length_ms)
     }
-}
 
-impl From<TimeInterval> for Range<Duration> {
-    #[inline]
-    fn from(interval: TimeInterval) -> Self {
-        interval.since()..interval.since() + interval.length()
+    /// Checks whether interval contains given timestamp
+    #[cfg(feature = "std")]
+    pub fn contains(&self, time: SystemTime) -> bool {
+        let since = self.since();
+        since <= time && time < since + self.length()
     }
 }
 
@@ -333,7 +345,9 @@ mod tests {
     use super::*;
 
     /// Sample timestamp
-    const TIMESTAMP: u64 = 1_647_443_386;
+    fn sample_timestamp() -> SystemTime {
+        SystemTime::UNIX_EPOCH + Duration::from_secs(1_647_443_386)
+    }
 
     /// Tests for `count_matches_in_interval()`
     mod count_matches_in_interval {
@@ -344,8 +358,8 @@ mod tests {
             // ----|-----[-----)-------
             //     p    i1     i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP - 5));
-            let since = Duration::from_secs(TIMESTAMP);
+            let schedule = Schedule::starting_at(sample_timestamp() - Duration::from_secs(5));
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 0);
@@ -357,8 +371,8 @@ mod tests {
             // ----[---------)------
             //   p, i1      i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP));
-            let since = Duration::from_secs(TIMESTAMP);
+            let schedule = Schedule::starting_at(sample_timestamp());
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 1);
@@ -369,8 +383,8 @@ mod tests {
             // ----[------|-----)----
             //     i1     p    i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 5));
-            let since = Duration::from_secs(TIMESTAMP);
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(5));
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 1);
@@ -382,8 +396,8 @@ mod tests {
             // ----[---------)------
             //    i1      i2, p
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 10));
-            let since = Duration::from_secs(TIMESTAMP);
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(10));
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 0);
@@ -394,9 +408,9 @@ mod tests {
             // ----[------|-----)----*----
             //     i1     p    i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 5))
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(5))
                 .with_period(Duration::from_secs(30));
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 1);
@@ -407,9 +421,9 @@ mod tests {
             // ----|------[-----)----*----
             //     p     i1    i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(10));
-            let since = Duration::from_secs(TIMESTAMP + 35);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(10));
+            let since = SystemTime::UNIX_EPOCH + Duration::from_secs(35);
             let length = Duration::from_secs(4);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 0);
@@ -420,9 +434,9 @@ mod tests {
             // ----[----)----|-----*-----*----
             //     i1   i2   p
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(6));
-            let since = Duration::from_secs(TIMESTAMP - 10);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(6));
+            let since = sample_timestamp() - Duration::from_secs(10);
             let length = Duration::from_secs(4);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 0);
@@ -433,9 +447,9 @@ mod tests {
             // ----[------|----*----*----*--)-*----
             //     i1     p                i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(6));
-            let since = Duration::from_secs(TIMESTAMP - 10);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(6));
+            let since = sample_timestamp() - Duration::from_secs(10);
             let length = Duration::from_secs(30);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 4);
@@ -446,9 +460,9 @@ mod tests {
             // ----|----*--[----*----*----*----*----)----*----
             //     p      i1                       i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_millis(600));
-            let since = Duration::from_secs(TIMESTAMP + 3) + Duration::from_millis(500);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_millis(600));
+            let since = sample_timestamp() + Duration::from_secs(3) + Duration::from_millis(500);
             let length = Duration::from_secs(2);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 4);
@@ -460,9 +474,9 @@ mod tests {
             // ----|-------[----)--*-------*--
             //     p      i1   i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP - 10))
+            let schedule = Schedule::starting_at(sample_timestamp() - Duration::from_secs(10))
                 .with_period(Duration::from_secs(10));
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(5);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 1);
@@ -474,9 +488,9 @@ mod tests {
             // ----[----|----)----*----*----
             //     i1   p    i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(5));
-            let since = Duration::from_secs(TIMESTAMP - 10);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(5));
+            let since = sample_timestamp() - Duration::from_secs(10);
             let length = Duration::from_secs(15);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 1);
@@ -488,9 +502,9 @@ mod tests {
             // ----|---[----)--------*----
             //     p   i1   i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP - 10))
+            let schedule = Schedule::starting_at(sample_timestamp() - Duration::from_secs(10))
                 .with_period(Duration::from_secs(15));
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(5);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 0);
@@ -502,9 +516,9 @@ mod tests {
             // ----[-*-*-*-*-*-*-)-*-*-*
             //   p, i1           i2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(1));
-            let since = Duration::from_secs(TIMESTAMP);
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(1));
+            let since = sample_timestamp();
             let length = Duration::from_secs(7);
             let interval = TimeInterval::new(since, length);
             assert_eq!(count_matches_in_interval(&schedule, &interval), 7);
@@ -521,15 +535,15 @@ mod tests {
             // ----|---[--*--)--*--[--*--)----
             //     s   p1    p2   c1    c2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP))
-                .with_period(Duration::from_secs(10));
+            let schedule =
+                Schedule::starting_at(sample_timestamp()).with_period(Duration::from_secs(10));
             let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
 
-            let since = Duration::from_secs(TIMESTAMP + 5);
+            let since = sample_timestamp() + Duration::from_secs(5);
             let length = Duration::from_secs(10);
             let prev_interval = TimeInterval::new(since, length);
 
-            let since = Duration::from_secs(TIMESTAMP + 25);
+            let since = sample_timestamp() + Duration::from_secs(25);
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
 
@@ -547,15 +561,15 @@ mod tests {
             // -------[--|--)--*--[--*--)----
             //        p1 s  p2   c1    c2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 5))
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(5))
                 .with_period(Duration::from_secs(10));
             let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
 
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let prev_interval = TimeInterval::new(since, length);
 
-            let since = Duration::from_secs(TIMESTAMP + 20);
+            let since = sample_timestamp() + Duration::from_secs(20);
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
 
@@ -573,15 +587,15 @@ mod tests {
             // -------[----)--|--[--*--)----
             //        p1   p2 s  c1    c2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 15))
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(15))
                 .with_period(Duration::from_secs(10));
             let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
 
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let prev_interval = TimeInterval::new(since, length);
 
-            let since = Duration::from_secs(TIMESTAMP + 20);
+            let since = sample_timestamp() + Duration::from_secs(20);
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
 
@@ -599,15 +613,15 @@ mod tests {
             // -------[----)----[--|--)----
             //        p1   p2   c1 s  c2
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 25))
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(25))
                 .with_period(Duration::from_secs(10));
             let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
 
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let prev_interval = TimeInterval::new(since, length);
 
-            let since = Duration::from_secs(TIMESTAMP + 20);
+            let since = sample_timestamp() + Duration::from_secs(20);
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
 
@@ -625,15 +639,15 @@ mod tests {
             // -------[----)----[----)--|--
             //        p1   p2   c1   c2 s
 
-            let schedule = Schedule::starting_at(Duration::from_secs(TIMESTAMP + 35))
+            let schedule = Schedule::starting_at(sample_timestamp() + Duration::from_secs(35))
                 .with_period(Duration::from_secs(10));
             let filter = TimeEventFilter(ExecutionTime::Schedule(schedule));
 
-            let since = Duration::from_secs(TIMESTAMP);
+            let since = sample_timestamp();
             let length = Duration::from_secs(10);
             let prev_interval = TimeInterval::new(since, length);
 
-            let since = Duration::from_secs(TIMESTAMP + 20);
+            let since = sample_timestamp() + Duration::from_secs(20);
             let length = Duration::from_secs(10);
             let interval = TimeInterval::new(since, length);
 
diff --git a/data_model/src/transaction.rs b/data_model/src/transaction.rs
index e268e46c13c..3f2b555b7e1 100644
--- a/data_model/src/transaction.rs
+++ b/data_model/src/transaction.rs
@@ -7,6 +7,8 @@ use core::{
     num::{NonZeroU32, NonZeroU64},
     time::Duration,
 };
+#[cfg(feature = "std")]
+use std::time::SystemTime;
 
 use derive_more::{DebugCustom, Display};
 #[cfg(feature = "http")]
@@ -250,11 +252,12 @@ impl SignedTransaction {
         &tx.payload.metadata
     }
 
-    /// Creation timestamp as [`core::time::Duration`]
+    /// Creation timestamp
     #[inline]
-    pub fn creation_time(&self) -> Duration {
+    #[cfg(feature = "std")]
+    pub fn creation_time(&self) -> SystemTime {
         let SignedTransaction::V1(tx) = self;
-        Duration::from_millis(tx.payload.creation_time_ms)
+        SystemTime::UNIX_EPOCH + Duration::from_millis(tx.payload.creation_time_ms)
     }
 
     /// If transaction is not committed by this time it will be dropped.
@@ -724,8 +727,13 @@ mod http {
         }
 
         /// Set creation time of transaction
-        pub fn set_creation_time(&mut self, value: Duration) -> &mut Self {
-            self.payload.creation_time_ms = u64::try_from(value.as_millis())
+        #[cfg(feature = "std")]
+        pub fn set_creation_time(&mut self, value: SystemTime) -> &mut Self {
+            self.payload.creation_time_ms = value
+                .duration_since(SystemTime::UNIX_EPOCH)
+                .expect("INTERNAL BUG: Failed to get the current system time")
+                .as_millis()
+                .try_into()
                 .expect("INTERNAL BUG: Unix timestamp exceedes u64::MAX");
             self
         }