Doxygen
Loading...
Searching...
No Matches
datetime.cpp File Reference
#include <cstdlib>
#include <chrono>
#include <memory>
#include <array>
#include <functional>
#include "regex.h"
#include "datetime.h"
#include "config.h"
#include "portable.h"
#include "language.h"
#include "message.h"
Include dependency graph for datetime.cpp:

Go to the source code of this file.

Classes

struct  SpecFormat
struct  DateTimeField

Typedefs

using TMFieldAssigner = std::function< void(std::tm &,int value) >

Functions

std::tm getCurrentDateTime ()
 Returns the filled in std::tm for the current date and time.
QCString dateToString (DateTimeType includeTime)
 Returns the current date, when includeTime is set also the time is provided.
QCString yearToString ()
 Returns the current year as a string.
static void determine_weekday (std::tm &tm)
QCString dateTimeFromString (const QCString &spec, std::tm &dt, int &format)
 Returns the filled in std::tm for a given string representing a date and/or time.
QCString formatDateTime (const QCString &format, const std::tm &dt, int &formatUsed)
 Return a string representation for a given std::tm value that is formatted according to the pattern given by a format.

Variables

static std::array g_specFormats
static std::array g_assignValues

Typedef Documentation

◆ TMFieldAssigner

using TMFieldAssigner = std::function< void(std::tm &,int value) >

Definition at line 89 of file datetime.cpp.

Function Documentation

◆ dateTimeFromString()

QCString dateTimeFromString ( const QCString & spec,
std::tm & dt,
int & format )

Returns the filled in std::tm for a given string representing a date and/or time.

Parameters
[in]specThe string representation of the date and/or time Possible formats:
  • the empty string: the current date and time is returned

  • YYYY-MM-DD HH:MM:SS: the date and time are fully specified

  • YYYY-MM-DD HH:MM: the date and time without seconds

  • YYYY-MM-DD: the date without time

  • HH:MM:SS: the time with seconds but without date

  • HH:MM: the time without seconds and without date

[out]dtThe corresponding datetime value.
[out]formatThe parts that have been found in spec; a bitwise or of SF_Date, SF_Time and SF_Seconds.
Returns
An empty string if the spec has a supported format, or an error message if the format is invalid.

Definition at line 133 of file datetime.cpp.

134{
135 // for an empty spec field return the current date and time
136 dt = getCurrentDateTime();
137 if (spec.isEmpty())
138 {
139 format = SF_Date | SF_Time | SF_Seconds;
140 return QCString();
141 }
142
143 // find a matching pattern
144 const std::string &s = spec.str();
145 for (const auto &fmt : g_specFormats)
146 {
147 reg::Match m;
148 if (reg::match(s,m,fmt.re)) // match found
149 {
150 for (int i=0; i<fmt.count; i++)
151 {
152 int value = std::atoi(m[i+1].str().c_str());
153 const DateTimeField &dtf = g_assignValues[i+fmt.offset];
154 if (value<dtf.minVal || value>dtf.maxVal) // check if the value is in the expected range
155 {
156 return QCString().sprintf("value for %s is %d which is outside of the value range [%d..%d]",
157 dtf.name, value, dtf.minVal, dtf.maxVal);
158 }
159 dtf.assigner(dt,value);
160 }
161 format = fmt.format;
162 if (format&SF_Date) // if we have a date also determine the weekday
163 {
165 }
166 return QCString();
167 }
168 }
169
170 // no matching pattern found
171 return "invalid or non representable date/time argument";
172}
This is an alternative implementation of QCString.
Definition qcstring.h:101
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
const std::string & str() const
Definition qcstring.h:552
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
Object representing the matching results.
Definition regex.h:151
std::tm getCurrentDateTime()
Returns the filled in std::tm for the current date and time.
Definition datetime.cpp:29
static void determine_weekday(std::tm &tm)
Definition datetime.cpp:120
static std::array g_assignValues
Definition datetime.cpp:110
static std::array g_specFormats
Definition datetime.cpp:100
constexpr int SF_Seconds
the seconds are presenting in the format string
Definition datetime.h:26
constexpr int SF_Date
Date and time related functions.
Definition datetime.h:24
constexpr int SF_Time
a time is presenting in the format string
Definition datetime.h:25
Definition message.h:144
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855
TMFieldAssigner assigner
Definition datetime.cpp:93
const char * name
Definition datetime.cpp:96

References DateTimeField::assigner, determine_weekday(), g_assignValues, g_specFormats, getCurrentDateTime(), QCString::isEmpty(), reg::match(), DateTimeField::maxVal, DateTimeField::minVal, DateTimeField::name, SF_Date, SF_Seconds, SF_Time, QCString::sprintf(), and QCString::str().

Referenced by DocPara::handleShowDate(), and showDate().

◆ dateToString()

QCString dateToString ( DateTimeType includeTime)

Returns the current date, when includeTime is set also the time is provided.

Parameters
[in]includeTimeinclude the time in the output

Definition at line 62 of file datetime.cpp.

63{
64 auto current = getCurrentDateTime();
65 return theTranslator->trDateTime(current.tm_year + 1900,
66 current.tm_mon + 1,
67 current.tm_mday,
68 (current.tm_wday+6)%7+1, // map: Sun=0..Sat=6 to Mon=1..Sun=7
69 current.tm_hour,
70 current.tm_min,
71 current.tm_sec,
72 includeTime);
73}
Translator * theTranslator
Definition language.cpp:71

References getCurrentDateTime(), and theTranslator.

Referenced by RTFGenerator::endIndexSection(), ManGenerator::endTitleHead(), recordMetadata(), substituteLatexKeywords(), and writeDefaultStyleSheet().

◆ determine_weekday()

void determine_weekday ( std::tm & tm)
static

Definition at line 120 of file datetime.cpp.

121{
122 auto cpy = tm;
123 // there are some problems when the hr:min:sec are on 00:00:00 in determining the weekday
124 cpy.tm_hour = 12;
125 const auto as_time_t = std::mktime( &cpy ) ;
126 if (as_time_t != -1)
127 {
128 cpy = *std::localtime( &as_time_t ) ;
129 tm.tm_wday = cpy.tm_wday;
130 }
131}

Referenced by dateTimeFromString().

◆ formatDateTime()

QCString formatDateTime ( const QCString & format,
const std::tm & dt,
int & formatUsed )

Return a string representation for a given std::tm value that is formatted according to the pattern given by a format.

Parameters
[in]formatthe string used for format the date and time, e.g. Y-m-d
[in]dtthe date and time value to fill in
[out]formatUsedA bitwise OR of SF_Date, SF_Time and SF_Seconds representing the the types of markers found in the format string.

Definition at line 174 of file datetime.cpp.

175{
176 formatUsed = 0;
177 auto getYear = [](const std::tm &dat) { return dat.tm_year+1900; };
178 auto getMonth = [](const std::tm &dat) { return dat.tm_mon+1; };
179 auto getDay = [](const std::tm &dat) { return dat.tm_mday; };
180 auto getDayOfWeek = [](const std::tm &dat) { return (dat.tm_wday+6)%7+1; };
181 QCString result;
182 result.reserve(256);
183 auto addInt = [&result](const char *fmt,int value) {
184 char tmp[50];
185 qsnprintf(tmp,50,fmt,value);
186 result+=tmp;
187 };
188 char c = 0;
189 const char *p = format.data();
190 const char *fmt_zero = "%02d";
191 const char *fmt_nonzero = "%d";
192 const char *fmt_selected = nullptr;
193 if (p==nullptr) return QCString();
194 while ((c=*p++))
195 {
196 char nc = *p;
197 switch (c)
198 {
199 case '%':
200 fmt_selected = nc=='-' ? fmt_nonzero : fmt_zero; // %-H produces 1 and %H produces 01
201 if (nc=='-') nc=*++p; // skip over -
202 switch (nc)
203 {
204 case '%': result+='%'; break;
205 case 'y': addInt(fmt_selected,getYear(dt)%100); formatUsed|=SF_Date; break;
206 case 'Y': addInt("%d",getYear(dt)); formatUsed|=SF_Date; break;
207 case 'm': addInt(fmt_selected,getMonth(dt)); formatUsed|=SF_Date; break;
208 case 'b': result+=theTranslator->trMonth(getMonth(dt),false,false); formatUsed|=SF_Date; break;
209 case 'B': result+=theTranslator->trMonth(getMonth(dt),false,true); formatUsed|=SF_Date; break;
210 case 'd': addInt(fmt_selected,getDay(dt)); formatUsed|=SF_Date; break;
211 case 'u': addInt("%d",getDayOfWeek(dt)); /* Monday = 1 ... Sunday = 7 */ formatUsed|=SF_Date; break;
212 case 'w': addInt("%d",getDayOfWeek(dt)%7); /* Sunday = 0 ... Saturday = 6 */ formatUsed|=SF_Date; break;
213 case 'a': result+=theTranslator->trDayOfWeek(getDayOfWeek(dt),false,false); formatUsed|=SF_Date; break;
214 case 'A': result+=theTranslator->trDayOfWeek(getDayOfWeek(dt),false,true); formatUsed|=SF_Date; break;
215 case 'H': addInt(fmt_selected,dt.tm_hour); formatUsed|=SF_Time; break;
216 case 'I': addInt(fmt_selected,dt.tm_hour%12); formatUsed|=SF_Time; break;
217 case 'p': result+=theTranslator->trDayPeriod(dt.tm_hour>=12); formatUsed|=SF_Time; break;
218 case 'M': addInt(fmt_selected,dt.tm_min); formatUsed|=SF_Time; break;
219 case 'S': addInt(fmt_selected,dt.tm_sec); formatUsed|=SF_Seconds; break;
220 default:
221 result+=c;
222 if (*(p-1)=='-') result+='-';
223 result+=nc;
224 break;
225 }
226 p++;
227 break;
228 default:
229 result+=c;
230 break;
231 }
232 }
233 return result;
234}
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
#define qsnprintf
Definition qcstring.h:49

References QCString::data(), qsnprintf, QCString::reserve(), SF_Date, SF_Seconds, SF_Time, and theTranslator.

Referenced by DocPara::handleShowDate(), and showDate().

◆ getCurrentDateTime()

std::tm getCurrentDateTime ( )

Returns the filled in std::tm for the current date and time.

Definition at line 29 of file datetime.cpp.

30{
31 QCString sourceDateEpoch = Portable::getenv("SOURCE_DATE_EPOCH");
32 if (!sourceDateEpoch.isEmpty()) // see https://reproducible-builds.org/specs/source-date-epoch/
33 {
34 bool ok = false;
35 uint64_t epoch = sourceDateEpoch.toUInt64(&ok);
36 if (!ok)
37 {
38 static bool warnedOnce=FALSE;
39 if (!warnedOnce)
40 {
41 warn_uncond("Environment variable SOURCE_DATE_EPOCH does not contain a valid number; value is '{}'\n",
42 sourceDateEpoch);
43 warnedOnce=TRUE;
44 }
45 }
46 else // use given epoch value as current 'built' time
47 {
48 auto epoch_start = std::chrono::time_point<std::chrono::system_clock>{};
49 auto epoch_seconds = std::chrono::seconds(epoch);
50 auto build_time = epoch_start + epoch_seconds;
51 std::time_t time = std::chrono::system_clock::to_time_t(build_time);
52 return *gmtime(&time);
53 }
54 }
55
56 // return current local time
57 auto now = std::chrono::system_clock::now();
58 std::time_t time = std::chrono::system_clock::to_time_t(now);
59 return *localtime(&time);
60}
uint64_t toUInt64(bool *ok=nullptr, int base=10) const
Definition qcstring.cpp:414
#define warn_uncond(fmt,...)
Definition message.h:122
QCString getenv(const QCString &variable)
Definition portable.cpp:322
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34

References FALSE, Portable::getenv(), QCString::isEmpty(), QCString::toUInt64(), TRUE, and warn_uncond.

Referenced by dateTimeFromString(), dateToRTFDateString(), dateToString(), and yearToString().

◆ yearToString()

QCString yearToString ( )

Returns the current year as a string.

Definition at line 75 of file datetime.cpp.

76{
77 auto current = getCurrentDateTime();
78 return QCString().setNum(current.tm_year+1900);
79}
QCString & setNum(short n)
Definition qcstring.h:459

References getCurrentDateTime(), and QCString::setNum().

Referenced by substituteLatexKeywords(), and writeDefaultStyleSheet().

Variable Documentation

◆ g_assignValues

std::array g_assignValues
static
Initial value:
{
DateTimeField{ [](std::tm &tm,int value) { tm.tm_year = value-1900; }, 1900, 9999, "year" },
DateTimeField{ [](std::tm &tm,int value) { tm.tm_mon = value-1; }, 1, 12, "month" },
DateTimeField{ [](std::tm &tm,int value) { tm.tm_mday = value; }, 1, 31, "day" },
DateTimeField{ [](std::tm &tm,int value) { tm.tm_hour = value; }, 0, 23, "hour" },
DateTimeField{ [](std::tm &tm,int value) { tm.tm_min = value; }, 0, 59, "minute" },
DateTimeField{ [](std::tm &tm,int value) { tm.tm_sec = value; }, 0, 59, "second" }
}

Definition at line 109 of file datetime.cpp.

110{
111 // assigner, minVal, maxVal, name
112 DateTimeField{ [](std::tm &tm,int value) { tm.tm_year = value-1900; }, 1900, 9999, "year" },
113 DateTimeField{ [](std::tm &tm,int value) { tm.tm_mon = value-1; }, 1, 12, "month" },
114 DateTimeField{ [](std::tm &tm,int value) { tm.tm_mday = value; }, 1, 31, "day" },
115 DateTimeField{ [](std::tm &tm,int value) { tm.tm_hour = value; }, 0, 23, "hour" },
116 DateTimeField{ [](std::tm &tm,int value) { tm.tm_min = value; }, 0, 59, "minute" },
117 DateTimeField{ [](std::tm &tm,int value) { tm.tm_sec = value; }, 0, 59, "second" }
118};

Referenced by dateTimeFromString().

◆ g_specFormats

std::array g_specFormats
static
Initial value:
{
SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+)\s*(\d+):(\d+):(\d+))"), 6, 0, SF_Date|SF_Time|SF_Seconds },
SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+)\s*(\d+):(\d+))"), 5, 0, SF_Date|SF_Time },
SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+))"), 3, 0, SF_Date },
SpecFormat{ std::string_view(R"((\d+):(\d+):(\d+))"), 3, 3, SF_Time|SF_Seconds },
SpecFormat{ std::string_view(R"((\d+):(\d+))"), 2, 3, SF_Time }
}

Definition at line 99 of file datetime.cpp.

100{
101 // regular expression, num values, offset, format bits
102 SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+)\s*(\d+):(\d+):(\d+))"), 6, 0, SF_Date|SF_Time|SF_Seconds }, // format 13-04-2015 12:34:56
103 SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+)\s*(\d+):(\d+))"), 5, 0, SF_Date|SF_Time }, // format 13-04-2015 12:34
104 SpecFormat{ std::string_view(R"((\d+)-(\d+)-(\d+))"), 3, 0, SF_Date }, // format 13-04-2015
105 SpecFormat{ std::string_view(R"((\d+):(\d+):(\d+))"), 3, 3, SF_Time|SF_Seconds }, // format 12:34:56
106 SpecFormat{ std::string_view(R"((\d+):(\d+))"), 2, 3, SF_Time } // format 12:34
107};

Referenced by dateTimeFromString().