171 lines
6.5 KiB
C++
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_
|