Files
oemcrypto/util/include/wv_timestamp.h
2025-05-22 16:33:29 -07:00

171 lines
6.5 KiB
C++

// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_UTIL_WV_TIMESTAMP_H_
#define WVCDM_UTIL_WV_TIMESTAMP_H_
#include <inttypes.h>
#include <chrono>
#include "wv_class_utils.h"
#include "wv_duration.h"
namespace wvutil {
// The Timestamp class is a light-weight representation of a
// time point.
//
// Internally, the time is measured in Unix Time (milliseconds
// since January 1st, 1970 UTC (epoch)).
//
// For this library, we are not concerned about time points before
// January 1st, 1970; this class does not support negative epoch
// seconds. In addition, zero is treated as a special value
// which indicates an uninitialized time point.
//
// Min Timestamp: 1970-01-01 00:00:00.001 (epoch ms = 1)
// Max Timestamp: 9999-12-31 23:59:59.999 (epoch ms = 253402300799999)
class Timestamp {
public:
constexpr Timestamp() = default; // Defaults to "unset".
WVCDM_CONSTEXPR_DEFAULT_COPY_AND_MOVE(Timestamp);
// Create a Timestamp instance from Unix Time in epoch seconds.
// Optionally allowed to include |millisecond| (0 to 999).
// If |epoch_seconds| or |millisecond| are invalid values, then an
// uninitlaized Timestamp instance is returned.
static constexpr Timestamp FromUnixSeconds(uint64_t epoch_seconds,
uint32_t milliseconds = 0) {
if (milliseconds > 999u) return Timestamp();
return Timestamp(Seconds(epoch_seconds) + Milliseconds(milliseconds));
}
static constexpr Timestamp FromUnixSeconds(const Seconds& epoch_seconds,
uint32_t milliseconds = 0) {
if (milliseconds > 999u) return Timestamp();
return Timestamp(epoch_seconds + Milliseconds(milliseconds));
}
// Create a Timestamp instance from Unix Time in epoch milliseconds.
// If |epoch_milliseconds| is an invalid value (zero), then an
// uninitlaized Timestamp instance is returned.
static constexpr Timestamp FromUnixMilliseconds(uint64_t epoch_milliseconds) {
return Timestamp(Milliseconds(epoch_milliseconds));
}
static constexpr Timestamp FromUnixMilliseconds(
const Milliseconds& epoch_milliseconds) {
return Timestamp(epoch_milliseconds);
}
// Obtain the minimum and maximum representable Timestamp.
static constexpr Timestamp Min() { return Timestamp(kMinMsDuration); }
static constexpr Timestamp Max() { return Timestamp(kMaxMsDuration); }
// == General Accessors ==
// Get the epoch seconds duration (rounding down milliseconds).
constexpr Seconds epoch_seconds() const {
return std::chrono::floor<Seconds>(epoch_milliseconds_);
}
// Get the milliseconds fraction of the epoch time (0-999).
constexpr uint32_t milliseconds() const {
return static_cast<uint32_t>(
(epoch_milliseconds_ - epoch_seconds()).count());
}
constexpr Milliseconds epoch_milliseconds() const {
return epoch_milliseconds_;
}
// As noted, the timestamp is considered "unset" if zero.
constexpr bool IsSet() const {
return epoch_milliseconds_ > Milliseconds::zero();
}
explicit constexpr operator bool() const { return IsSet(); }
constexpr void Clear() { epoch_milliseconds_ = kUnsetMsDuration; }
// == Comparisons ==
constexpr bool IsEqualTo(const Timestamp& other) const {
return epoch_milliseconds_ == other.epoch_milliseconds_;
}
constexpr int64_t CompareTo(const Timestamp& other) const {
return static_cast<int64_t>(epoch_milliseconds_.count() -
other.epoch_milliseconds_.count());
}
WVCDM_DEFINE_CONSTEXPR_EQ_AND_CMP_OPERATORS(Timestamp);
// == Arithmetic Operations ==
// Duration-based addition/subtraction operations.
// Returns a new Timestamp instance with time point adjusted by
// the provided Duration.
// If current Timestamp instance is unset, or if result value
// is outside the range of valid Timestamp values, then an unset
// Timestamp is returned.
constexpr Timestamp operator+(const Duration& duration) const {
if (!IsSet()) return Timestamp();
return Timestamp(epoch_milliseconds_ + duration.total_milliseconds());
}
constexpr Timestamp operator-(const Duration& duration) const {
if (!IsSet()) return Timestamp();
return Timestamp(epoch_milliseconds_ - duration.total_milliseconds());
}
// Duration-based increment/decrement operators.
// Increment or decrement the Timestamp by the provided Duration
// amount.
// If current Timestamp instance is unset, then no action will
// occur. If result value is outside the range of valid Timestamp
// values, then Timestamp will be unset.
constexpr Timestamp& operator+=(const Duration& duration) {
if (!IsSet()) return *this;
epoch_milliseconds_ =
Normalize(epoch_milliseconds_ + duration.total_milliseconds());
return *this;
}
constexpr Timestamp& operator-=(const Duration& duration) {
if (!IsSet()) return *this;
epoch_milliseconds_ =
Normalize(epoch_milliseconds_ - duration.total_milliseconds());
return *this;
}
// Timestamp difference.
// Returns the duration between the two provided Timestamp
// instances.
// If either Timestamp instance is unset, then the resulting
// Duration is zero.
constexpr Duration operator-(const Timestamp& other) const {
if (!IsSet() || !other.IsSet()) return Duration();
return Duration(epoch_milliseconds_ - other.epoch_milliseconds_);
}
private:
static constexpr const uint64_t kMinMs = 1;
static constexpr const uint64_t kMaxMs = 253402300799999;
static constexpr const Milliseconds kMinMsDuration = Milliseconds(kMinMs);
static constexpr const Milliseconds kMaxMsDuration = Milliseconds(kMaxMs);
static constexpr const Milliseconds kUnsetMsDuration = Milliseconds::zero();
static constexpr bool IsInRange(const Milliseconds& epoch_milliseconds) {
return epoch_milliseconds >= kMinMsDuration &&
epoch_milliseconds <= kMaxMsDuration;
}
// Ensures the provided |epoch_milliseconds| is in range of the
// Timestamp class; otherwise returns an unset duration value.
static constexpr Milliseconds Normalize(
const Milliseconds& epoch_milliseconds) {
return IsInRange(epoch_milliseconds) ? epoch_milliseconds
: kUnsetMsDuration;
}
constexpr Timestamp(const Milliseconds& epoch_milliseconds)
: epoch_milliseconds_(Normalize(epoch_milliseconds)) {}
Milliseconds epoch_milliseconds_ = kUnsetMsDuration;
}; // class Timestamp
} // namespace wvutil
#endif // WVCDM_UTIL_WV_TIMESTAMP_H_