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.
DString dateToString (DateTimeType includeTime)
 Returns the current date, when includeTime is set also the time is provided.
DString yearToString ()
 Returns the current year as a string.
static void determine_weekday (std::tm &tm)
DString dateTimeFromString (const DString &spec, std::tm &dt, int &format)
 Returns the filled in std::tm for a given string representing a date and/or time.
DString formatDateTime (const DString &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()

DString dateTimeFromString ( const DString & 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.empty())
138 {
139 format = SF_Date | SF_Time | SF_Seconds;
140 return DString();
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 DString().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 DString();
167 }
168 }
169
170 // no matching pattern found
171 return "invalid or non representable date/time argument";
172}
DString()=default
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:153
const std::string & str() const
Definition dstring.h:634
Object representing the matching results.
Definition regex.h:154
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:858
TMFieldAssigner assigner
Definition datetime.cpp:93
const char * name
Definition datetime.cpp:96

References DateTimeField::assigner, dateTimeFromString(), determine_weekday(), DString::DString(), DString::empty(), g_assignValues, g_specFormats, getCurrentDateTime(), reg::match(), DateTimeField::maxVal, DateTimeField::minVal, DateTimeField::name, SF_Date, SF_Seconds, SF_Time, and DString::str().

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

◆ dateToString()

DString 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}
virtual DString trDateTime(int year, int month, int day, int dayOfWeek, int hour, int minutes, int seconds, DateTimeType includeTime)=0
Translator * theTranslator
Definition language.cpp:71

References dateToString(), getCurrentDateTime(), theTranslator, and Translator::trDateTime().

Referenced by dateToString(), 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}

References determine_weekday().

Referenced by dateTimeFromString(), and determine_weekday().

◆ formatDateTime()

DString formatDateTime ( const DString & 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 DString result;
182 result.reserve(256);
183 auto addInt = [&result](const char *fmt,int value) {
184 char tmp[50];
185 snprintf(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 DString();
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}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:89
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:222
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:162
virtual DString trDayOfWeek(int dayOfWeek, bool first_capital, bool full)=0
virtual DString trDayPeriod(bool period)=0
virtual DString trMonth(int month, bool first_capital, bool full)=0

References DString::data(), DString::DString(), formatDateTime(), DString::reserve(), SF_Date, SF_Seconds, SF_Time, theTranslator, Translator::trDayOfWeek(), Translator::trDayPeriod(), and Translator::trMonth().

Referenced by formatDateTime(), 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 DString sourceDateEpoch = Portable::getenv("SOURCE_DATE_EPOCH");
32 if (!sourceDateEpoch.empty()) // 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 dstring.cpp:342
#define warn_uncond(fmt,...)
Definition message.h:122
DString getenv(const DString &variable)
Definition portable.cpp:321

References DString::empty(), getCurrentDateTime(), Portable::getenv(), DString::toUInt64(), and warn_uncond.

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

◆ yearToString()

DString yearToString ( )

Returns the current year as a string.

Definition at line 75 of file datetime.cpp.

76{
77 auto current = getCurrentDateTime();
78 return DString().setNum(current.tm_year+1900);
79}

References DString::DString(), getCurrentDateTime(), and yearToString().

Referenced by substituteLatexKeywords(), writeDefaultStyleSheet(), and yearToString().

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().