Doxygen
Loading...
Searching...
No Matches
datetime.cpp File Reference
#include "datetime.h"
#include <array>
#include <chrono>
#include <cstdlib>
#include <functional>
#include "language.h"
#include "message.h"
#include "portable.h"
#include "regex.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 91 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 135 of file datetime.cpp.

136{
137 // for an empty spec field return the current date and time
138 dt = getCurrentDateTime();
139 if (spec.empty())
140 {
141 format = SF_Date | SF_Time | SF_Seconds;
142 return DString();
143 }
144
145 // find a matching pattern
146 const std::string &s = spec.str();
147 for (const auto &fmt : g_specFormats)
148 {
149 reg::Match m;
150 if (reg::match(s,m,fmt.re)) // match found
151 {
152 for (int i=0; i<fmt.count; i++)
153 {
154 int value = std::atoi(m[i+1].str().c_str());
155 const DateTimeField &dtf = g_assignValues[i+fmt.offset];
156 if (value<dtf.minVal || value>dtf.maxVal) // check if the value is in the expected range
157 {
158 return DString().sprintf("value for %s is %d which is outside of the value range [%d..%d]",
159 dtf.name, value, dtf.minVal, dtf.maxVal);
160 }
161 dtf.assigner(dt,value);
162 }
163 format = fmt.format;
164 if (format&SF_Date) // if we have a date also determine the weekday
165 {
167 }
168 return DString();
169 }
170 }
171
172 // no matching pattern found
173 return "invalid or non representable date/time argument";
174}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
const std::string & str() const
Definition dstring.h:645
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:31
static void determine_weekday(std::tm &tm)
Definition datetime.cpp:122
static std::array g_assignValues
Definition datetime.cpp:112
static std::array g_specFormats
Definition datetime.cpp:102
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:146
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:861
TMFieldAssigner assigner
Definition datetime.cpp:95
const char * name
Definition datetime.cpp:98

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

Referenced by 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 64 of file datetime.cpp.

65{
66 auto current = getCurrentDateTime();
67 return theTranslator->trDateTime(current.tm_year + 1900,
68 current.tm_mon + 1,
69 current.tm_mday,
70 (current.tm_wday+6)%7+1, // map: Sun=0..Sat=6 to Mon=1..Sun=7
71 current.tm_hour,
72 current.tm_min,
73 current.tm_sec,
74 includeTime);
75}
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:76

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

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

◆ determine_weekday()

void determine_weekday ( std::tm & tm)
static

Definition at line 122 of file datetime.cpp.

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

Referenced by dateTimeFromString().

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

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

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

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

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

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

◆ yearToString()

DString yearToString ( )

Returns the current year as a string.

Definition at line 77 of file datetime.cpp.

78{
79 auto current = getCurrentDateTime();
80 return DString().setNum(current.tm_year+1900);
81}
DString & setNum(short n)
Definition dstring.h:552

References getCurrentDateTime(), and DString::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 111 of file datetime.cpp.

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

Referenced by dateTimeFromString().