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 "growbuf.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 90 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 134 of file datetime.cpp.

135{
136 // for an empty spec field return the current date and time
137 dt = getCurrentDateTime();
138 if (spec.isEmpty())
139 {
140 format = SF_Date | SF_Time | SF_Seconds;
141 return QCString();
142 }
143
144 // find a matching pattern
145 std::string s = spec.str();
146 for (const auto &fmt : g_specFormats)
147 {
148 reg::Match m;
149 if (reg::match(s,m,fmt.re)) // match found
150 {
151 for (int i=0; i<fmt.count; i++)
152 {
153 int value = std::atoi(m[i+1].str().c_str());
154 const DateTimeField &dtf = g_assignValues[i+fmt.offset];
155 if (value<dtf.minVal || value>dtf.maxVal) // check if the value is in the expected range
156 {
157 return QCString().sprintf("value for %s is %d which is outside of the value range [%d..%d]",
158 dtf.name, value, dtf.minVal, dtf.maxVal);
159 }
160 dtf.assigner(dt,value);
161 }
162 format = fmt.format;
163 if (format&SF_Date) // if we have a date also determine the weekday
164 {
166 }
167 return QCString();
168 }
169 }
170
171 // no matching pattern found
172 return "invalid or non representable date/time argument";
173}
This is an alternative implementation of QCString.
Definition qcstring.h:101
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
const std::string & str() const
Definition qcstring.h:537
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
Object representing the matching results.
Definition regex.h:153
std::tm getCurrentDateTime()
Returns the filled in std::tm for the current date and time.
Definition datetime.cpp:30
static void determine_weekday(std::tm &tm)
Definition datetime.cpp:121
static std::array g_assignValues
Definition datetime.cpp:111
static std::array g_specFormats
Definition datetime.cpp:101
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 trace.h:153
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:759
TMFieldAssigner assigner
Definition datetime.cpp:94
const char * name
Definition datetime.cpp:97

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 63 of file datetime.cpp.

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

References getCurrentDateTime(), and theTranslator.

Referenced by RTFGenerator::endIndexSection(), ManGenerator::endTitleHead(), recordMetadata(), substituteHtmlKeywords(), substituteKeywords(), substituteLatexKeywords(), and HtmlGenerator::writeLogoAsString().

◆ determine_weekday()

static void determine_weekday ( std::tm & tm)
static

Definition at line 121 of file datetime.cpp.

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

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 175 of file datetime.cpp.

176{
177 formatUsed = 0;
178 auto getYear = [](const std::tm &dat) { return dat.tm_year+1900; };
179 auto getMonth = [](const std::tm &dat) { return dat.tm_mon+1; };
180 auto getDay = [](const std::tm &dat) { return dat.tm_mday; };
181 auto getDayOfWeek = [](const std::tm &dat) { return (dat.tm_wday+6)%7+1; };
182 GrowBuf growBuf;
183 char c = 0;
184 const char *p = format.data();
185 const char *fmt_zero = "%02d";
186 const char *fmt_nonzero = "%d";
187 const char *fmt_selected = nullptr;
188 if (p==nullptr) return QCString();
189 while ((c=*p++))
190 {
191 char nc = *p;
192 switch (c)
193 {
194 case '%':
195 fmt_selected = nc=='-' ? fmt_nonzero : fmt_zero; // %-H produces 1 and %H produces 01
196 if (nc=='-') nc=*++p; // skip over -
197 switch (nc)
198 {
199 case '%': growBuf.addChar('%'); break;
200 case 'y': growBuf.addInt(fmt_selected,getYear(dt)%100); formatUsed|=SF_Date; break;
201 case 'Y': growBuf.addInt("%d",getYear(dt)); formatUsed|=SF_Date; break;
202 case 'm': growBuf.addInt(fmt_selected,getMonth(dt)); formatUsed|=SF_Date; break;
203 case 'b': growBuf.addStr(theTranslator->trMonth(getMonth(dt),false,false)); formatUsed|=SF_Date; break;
204 case 'B': growBuf.addStr(theTranslator->trMonth(getMonth(dt),false,true)); formatUsed|=SF_Date; break;
205 case 'd': growBuf.addInt(fmt_selected,getDay(dt)); formatUsed|=SF_Date; break;
206 case 'u': growBuf.addInt("%d",getDayOfWeek(dt)); /* Monday = 1 ... Sunday = 7 */ formatUsed|=SF_Date; break;
207 case 'w': growBuf.addInt("%d",getDayOfWeek(dt)%7); /* Sunday = 0 ... Saturday = 6 */ formatUsed|=SF_Date; break;
208 case 'a': growBuf.addStr(theTranslator->trDayOfWeek(getDayOfWeek(dt),false,false)); formatUsed|=SF_Date; break;
209 case 'A': growBuf.addStr(theTranslator->trDayOfWeek(getDayOfWeek(dt),false,true)); formatUsed|=SF_Date; break;
210 case 'H': growBuf.addInt(fmt_selected,dt.tm_hour); formatUsed|=SF_Time; break;
211 case 'I': growBuf.addInt(fmt_selected,dt.tm_hour%12); formatUsed|=SF_Time; break;
212 case 'p': growBuf.addStr(theTranslator->trDayPeriod(dt.tm_hour>=12)); formatUsed|=SF_Time; break;
213 case 'M': growBuf.addInt(fmt_selected,dt.tm_min); formatUsed|=SF_Time; break;
214 case 'S': growBuf.addInt(fmt_selected,dt.tm_sec); formatUsed|=SF_Seconds; break;
215 default:
216 growBuf.addChar(c);
217 if (*(p-1)=='-') growBuf.addChar('-');
218 growBuf.addChar(nc);
219 break;
220 }
221 p++;
222 break;
223 default:
224 growBuf.addChar(c);
225 break;
226 }
227 }
228 growBuf.addChar(0);
229 return growBuf.get();
230}
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addInt(const char *fmt, int value)
Definition growbuf.h:109
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
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:159

References GrowBuf::addChar(), GrowBuf::addInt(), GrowBuf::addStr(), QCString::data(), GrowBuf::get(), 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 30 of file datetime.cpp.

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

References FALSE, Portable::getenv(), QCString::isEmpty(), qPrint(), 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 76 of file datetime.cpp.

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

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

Referenced by substituteKeywords().

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 110 of file datetime.cpp.

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

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 100 of file datetime.cpp.

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

Referenced by dateTimeFromString().