aboutsummaryrefslogtreecommitdiffstats
path: root/include/timeutils.h
blob: deeb1c17bf9ae760e6f49160c69bf9681154a337 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * InspIRCd -- Internet Relay Chat Daemon
 *
 *   Copyright (C) 2023-2025 Sadie Powell <sadie@sadiepowell.dev>
 *
 * This file is part of InspIRCd.  InspIRCd is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 2.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#pragma once

#include "utility/numeric.h"

namespace Duration
{
	/** Converts a string containing a duration to the number of seconds it
	 * represents returning 0 on error.
	 *
	 * The string should should be in the format 1y2w3d4h6m5s which represents
	 * one year, two weeks, three days, four hours, six minutes, and five
	 * seconds. If called with this duration 33,019,565 will be returned.
	 *
	 * @param str A string containing a duration.
	 * @return Either the number of seconds in the duration or 0 on error.
	 */
	CoreExport unsigned long From(const std::string& str);

	/** Determines whether a duration string is valid.
	 * @param str The duration string to check.
	 */
	CoreExport bool IsValid(const std::string& str);

	/** Converts a number of seconds to a human-readable duration string.
	 *
	 * e.g. 33,019,565 will result in 1 year, 2 weeks, 3 days, 4 hours, 6
	 * minutes, 5 seconds.
	 *
	 * @param duration The number of seconds to convert.
	 * @param brief Whether to round to the nearest time period.
	 */
	CoreExport std::string ToLongString(unsigned long duration, bool brief = false);

	/** Converts a number of seconds to a duration string.
	 *
	 * e.g. 33,019,565 will result in 1y2w3d4h6m5s which represents one year,
	 * two weeks, three days, four hours, six minutes, and five seconds.
	 *
	 * @param duration The number of seconds to convert.
	 */
	CoreExport std::string ToString(unsigned long duration);

	/** Attempts to converts a string containing a duration to the number of
	 * seconds it represents returning whether the conversion succeeded.
	 *
	 * The string should should be in the format 1y2w3d4h6m5s which represents
	 * one year, two weeks, three days, four hours, six minutes, and five
	 * seconds. If called with this duration 33,019,565 will be returned.
	 *
	 * @param str A string containing a duration.
	 * @param duration The location to store the resulting duration.
	 * @return True if the conversion succeeded; otherwise, false.
	 */
	CoreExport bool TryFrom(const std::string_view& str, unsigned long& duration);
}

namespace Time
{
	/** A short time format picked for being readable (e.g. "Sun 23 Mar 2025 10:20:30") */
	inline constexpr const char* DEFAULT_SHORT = "%a %d %b %Y %H:%M:%S";

	/** A long time format picked for being readable (e.g. "Sunday, 23 March 2025 @ 10:20:30 GMT"). */
	inline constexpr const char* DEFAULT_LONG = "%A, %d %B %Y @ %H:%M:%S %Z";

	/** The time format specified in ISO 8601 (e.g. "2025-03-23T10:20:30+0000") */
	inline constexpr const char* ISO_8601 = "%Y-%m-%dT%H:%M:%S%z";

	/** The time format specified in RFC 1123 (e.g. "Sun, 23 Mar 2025 10:20:30 GMT") */
	inline constexpr const char* RFC_1123 = "%a, %d %b %Y %H:%M:%S %Z";

	/** Calculates the time the specified number of seconds ago. This uses a saturating subtract so
	 * if the result is too large for time_t it will return the largest/smallest possible value.
	 * @param seconds The number of seconds from now to subtract from the current time.
	 */
	template<std::integral T>
	inline time_t Ago(T seconds)
	{
		return insp::saturating_sub<time_t>(ServerInstance->Time(), seconds);
	}

	/** Calculates the time in the specified number of seconds. This uses a saturating add so if the
	 * result is too large for time_t it will return the largest/smallest possible value.
	 * @param seconds The number of seconds from now to add to the current time.
	 */
	template<std::integral T>
	inline time_t In(T seconds)
	{
		return insp::saturating_add<time_t>(ServerInstance->Time(), seconds);
	}

	/** Converts a UNIX timestamp to a time string.
	 *
	 * @param ts The timestamp to convert to a string.
	 * @param format A snprintf format string to output the timestamp in.
	 * @param utc If the timestamp is a UTC timestamp then true or false if the
	 *            timestamp is a local timestamp.
	 */
	CoreExport std::string ToString(time_t ts, const char* format = nullptr, bool utc = false);

	/** Converts a duration from now to a time string.
	 *
	 * @param duration The duration from now to convert to a string.
	 * @param format A snprintf format string to output the timestamp in.
	 * @param utc If the timestamp is a UTC timestamp then true or false if the
	 *            timestamp is a local timestamp.
	 */
	inline std::string FromNow(unsigned long duration, const char* format = nullptr, bool utc = false)
	{
		return ToString(In(duration), format, utc);
	}
}