Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
SUMOTime.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// Variables, methods, and tools for internal time representation
22/****************************************************************************/
23#include <config.h>
24
25#include <iostream>
26#ifdef HAVE_FMT
27#include <fmt/format.h>
28#endif
29#include "SUMOTime.h"
30#include "StringTokenizer.h"
31#include "StringUtils.h"
32#include "StdDefs.h"
33#include "MsgHandler.h"
34
35
36// ===========================================================================
37// type definitions
38// ===========================================================================
40
41
42// ===========================================================================
43// method definitions
44// ===========================================================================
45
47string2time(const std::string& r) {
48 if (r.find(":") == std::string::npos) {
49 const double time = StringUtils::toDouble(r);
50 if (time > STEPS2TIME(SUMOTime_MAX)) {
51 throw TimeFormatException("Input string '" + r + "' exceeds the time value range.");
52 }
53 return TIME2STEPS(time);
54 } else {
55 // try to parse dd:hh:mm:ss.s
56 std::vector<std::string> hrt = StringTokenizer(r, ":").getVector();
57 if (hrt.size() == 3) {
58 //std::cout << "parsed '" << r << "' as " << (3600 * string2time(hrt[0]) + 60 * string2time(hrt[1]) + string2time(hrt[2])) << "\n";
59 return 3600 * string2time(hrt[0]) + 60 * string2time(hrt[1]) + string2time(hrt[2]);
60 } else if (hrt.size() == 4) {
61 //std::cout << "parsed '" << r << "' as " << (24 * 3600 * string2time(hrt[0]) + 3600 * string2time(hrt[1]) + 60 * string2time(hrt[2]) + string2time(hrt[3])) << "\n";
62 return 24 * 3600 * string2time(hrt[0]) + 3600 * string2time(hrt[1]) + 60 * string2time(hrt[2]) + string2time(hrt[3]);
63 }
64 throw TimeFormatException("Input string '" + r + "' is not a valid time format (jj:HH:MM:SS.S).");
65 }
66}
67
68
69bool
70isTime(const std::string& r) {
71 if (r.find(":") == std::string::npos) {
72 if (StringUtils::isDouble(r)) {
74 } else {
75 return false;
76 }
77 } else {
78 // try to parse dd:hh:mm:ss.s
79 const std::vector<std::string> hrt = StringTokenizer(r, ":").getVector();
80 if (hrt.size() == 3) {
81 return StringUtils::isInt(hrt[0]) && StringUtils::isInt(hrt[1]) && StringUtils::isInt(hrt[2]);
82 } else if (hrt.size() == 4) {
83 return StringUtils::isInt(hrt[0]) && StringUtils::isInt(hrt[1]) && StringUtils::isInt(hrt[2]) && StringUtils::isDouble(hrt[3]);
84 } else {
85 return false;
86 }
87 }
88}
89
90
91// append the digits of value, padded with leading zeros to the given width
92static void
93appendPadded(std::string& result, SUMOTime value, int width) {
94#ifdef HAVE_FMT
95 const fmt::format_int digits(value);
96#else
97 const std::string digits = std::to_string(value);
98#endif
99 if ((int)digits.size() < width) {
100 result.append(width - (int)digits.size(), '0');
101 }
102 result.append(digits.data(), digits.size());
103}
104
105
106std::string
107time2string(SUMOTime t, bool humanReadable) {
108 const bool negative = t < 0;
109 // needed for signed zero errors, see #5926
110 // llabs(SUMOTime_MIN) would create overflow and must be handleed separately
111 t = t == SUMOTime_MIN ? SUMOTime_MAX : (SUMOTime)llabs(t);
112 SUMOTime scale = (SUMOTime)pow(10, MAX2(0, 3 - gPrecision));
113 if (scale > 1) {
114 if (t != SUMOTime_MAX) {
115 t = (t + scale / 2) / scale;
116 } else {
117 scale = 1;
118 }
119 }
120 const SUMOTime second = TIME2STEPS(1) / scale;
121 std::string result = negative ? "-" : "";
122 if (humanReadable) {
123 const SUMOTime minute = 60 * second;
124 const SUMOTime hour = 60 * minute;
125 const SUMOTime day = 24 * hour;
126 // 123456 -> "00:00:12.34"
127 if (t > day) {
128 appendPadded(result, t / day, 0);
129 result += ':';
130 t %= day;
131 }
132 appendPadded(result, t / hour, 2);
133 result += ':';
134 t %= hour;
135 appendPadded(result, t / minute, 2);
136 result += ':';
137 t %= minute;
138 appendPadded(result, t / second, 2);
139 t %= second;
140 if (t != 0 || TS < 1.) {
141 result += '.';
142 appendPadded(result, t, MIN2(3, gPrecision));
143 }
144 return result;
145 }
146 appendPadded(result, t / second, 0);
147 result += '.';
148 appendPadded(result, t % second, MIN2(3, gPrecision));
149 return result;
150}
151
152
153std::string
157
158
159std::string
160elapsedMs2string(long long int t) {
161 if (gHumanReadableTime) {
162 if (STEPS2TIME(t) > 60) {
163 // round to seconds
164 return time2string((t / 1000) * 1000);
165 } else {
166 return toString((double)t / 1000.0) + "s";
167 }
168 } else {
169 return time2string(t) + "s";
170 }
171}
172
173bool checkStepLengthMultiple(const SUMOTime t, const std::string& error, SUMOTime deltaT, SUMOTime begin) {
174 if (begin % deltaT == 0) {
175 if (t % deltaT != 0) {
176 WRITE_WARNING("The given time value " + time2string(t) + " is not a multiple of the step length " + time2string(deltaT) + error + ".")
177 }
178 } else {
179 if ((t - begin) % deltaT != 0) {
180 WRITE_WARNING("The given time value " + time2string(t) + " is not reached with step length " + time2string(deltaT)
181 + " and begin time " + time2string(begin) + error + ".")
182 }
183 }
184 // next line used to fix build
185 return false;
186}
187
188void checkTimeBounds(const double time) {
189 if (time > STEPS2TIME(SUMOTime_MAX)) {
190 throw TimeFormatException("Input time " + toString(time) + "s exceeds the time value range.");
191 }
192}
193
194
195/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
void checkTimeBounds(const double time)
check the valid SUMOTime range of double input and throw an error if out of bounds
Definition SUMOTime.cpp:188
std::string elapsedMs2string(long long int t)
convert ms to string for log output
Definition SUMOTime.cpp:160
SUMOTime DELTA_T
Definition SUMOTime.cpp:39
bool checkStepLengthMultiple(const SUMOTime t, const std::string &error, SUMOTime deltaT, SUMOTime begin)
check if given SUMOTime is multiple of the step length
Definition SUMOTime.cpp:173
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:47
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:107
bool isTime(const std::string &r)
check if the given string is a valid time
Definition SUMOTime.cpp:70
static void appendPadded(std::string &result, SUMOTime value, int width)
Definition SUMOTime.cpp:93
#define STEPS2TIME(x)
Definition SUMOTime.h:58
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SUMOTime_MIN
Definition SUMOTime.h:35
#define TS
Definition SUMOTime.h:45
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:27
bool gHumanReadableTime
Definition StdDefs.cpp:31
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
std::vector< std::string > getVector()
return vector of strings
static bool isDouble(const std::string &sData)
check if the given sData can be conveted to double
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool isInt(const std::string &sData)
check if the given sData can be converted to int