Spicy
time.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <arpa/inet.h>
6 
7 #include <limits>
8 #include <string>
9 #include <variant>
10 
11 #include <hilti/rt/extension-points.h>
12 #include <hilti/rt/types/interval.h>
13 
14 namespace hilti::rt {
15 
20 class Time {
21 public:
22  struct SecondTag {};
23  struct NanosecondTag {};
24 
26  Time() = default;
27 
33  explicit Time(hilti::rt::integer::safe<uint64_t> nsecs, NanosecondTag /*unused*/) : _nsecs(nsecs) {}
34 
41  explicit Time(double secs, SecondTag /*unused*/)
42  : _nsecs([&]() {
43  auto x = secs * 1'000'000'000;
44 
45  constexpr auto limits = std::numeric_limits<uint64_t>();
46  if ( x < static_cast<double>(limits.min()) || static_cast<double>(limits.max()) < x )
47  throw OutOfRange("value cannot be represented as a time");
48 
49  return integer::safe<uint64_t>(x);
50  }()) {}
51 
52  Time(const Time&) = default;
53  Time(Time&&) noexcept = default;
54  ~Time() = default;
55 
56  Time& operator=(const Time&) = default;
57  Time& operator=(Time&&) noexcept = default;
58 
60  double seconds() const { return _nsecs.Ref() / 1e9; }
61 
63  uint64_t nanoseconds() const { return _nsecs; }
64 
65  bool operator==(const Time& other) const { return _nsecs == other._nsecs; }
66  bool operator!=(const Time& other) const { return _nsecs != other._nsecs; }
67  bool operator<(const Time& other) const { return _nsecs < other._nsecs; }
68  bool operator<=(const Time& other) const { return _nsecs <= other._nsecs; }
69  bool operator>(const Time& other) const { return _nsecs > other._nsecs; }
70  bool operator>=(const Time& other) const { return _nsecs >= other._nsecs; }
71 
72  Time operator+(const Interval& other) const {
73  if ( other.nanoseconds() < 0 && (integer::safe<int64_t>(_nsecs) < (-other.nanoseconds())) )
74  throw RuntimeError(fmt("operation yielded negative time %d %d", _nsecs, other.nanoseconds()));
75 
76  return Time(_nsecs + other.nanoseconds(), NanosecondTag{});
77  }
78 
79  Time operator-(const Interval& other) const {
80  if ( _nsecs < other.nanoseconds() )
81  throw RuntimeError("operation yielded negative time");
82 
83  return Time(_nsecs - other.nanoseconds(), NanosecondTag());
84  }
85 
86  Interval operator-(const Time& other) const {
87  return Interval(integer::safe<int64_t>(_nsecs) - integer::safe<int64_t>(other._nsecs),
88  Interval::NanosecondTag());
89  }
90 
92  operator std::string() const;
93 
94 private:
95  hilti::rt::integer::safe<uint64_t> _nsecs = 0; ///< Nanoseconds since epoch.
96 };
97 
98 namespace time {
99 extern Time current_time();
100 extern Time mktime(uint64_t y, uint64_t m, uint64_t d, uint64_t H, uint64_t M, uint64_t S);
101 } // namespace time
102 
103 namespace detail::adl {
104 inline std::string to_string(const Time& x, adl::tag /*unused*/) { return x; }
105 } // namespace detail::adl
106 
107 inline std::ostream& operator<<(std::ostream& out, const Time& x) {
108  out << to_string(x);
109  return out;
110 }
111 
112 } // namespace hilti::rt
Definition: any.h:7
Definition: time.h:22
Time(double secs, SecondTag)
Definition: time.h:41
Time()=default
Time(hilti::rt::integer::safe< uint64_t > nsecs, NanosecondTag)
Definition: time.h:33
Definition: time.h:23
Definition: time.h:20