1 /*
2 datetime_utils.cpp MindForger thinking notebook
3
4 Copyright (C) 2016-2020 Martin Dvorak <martin.dvorak@mindforger.com>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "datetime_utils.h"
20
21 using namespace std;
22
23 namespace m8r {
24
datetimeNow()25 time_t datetimeNow()
26 {
27 return time(nullptr);
28 }
29
30 /**
31 * @brief Convert character string to datetime.
32 * @param datetime (struct tm*)calloc(1, sizeof(struct tm)) is expected for result creation.
33 */
datetimeFrom(const char * s,struct tm * datetime)34 struct tm* datetimeFrom(const char* s, struct tm* datetime)
35 {
36 strptime(s, "%Y-%m-%d %H:%M:%S", datetime);
37 return datetime;
38 }
39
40 /**
41 * @brief Convert datetime to character string.
42 * @param result char[50] or bigger is expected for result serialization.
43 */
datetimeTo(const struct tm * datetime,char * result)44 char* datetimeTo(const struct tm* datetime, char* result)
45 {
46 if(datetime->tm_isdst) {
47 #ifndef _WIN32
48 tm c {0,0,0,0,0,0,0,0,0,0,0}; // missing initializer required by older GCC versions 4.8.5 and older
49 #else
50 tm c {0,0,0,0,0,0,0,0,0};
51 #endif
52 memcpy(&c, datetime, sizeof(c));
53 if(c.tm_hour) {
54 c.tm_hour=datetime->tm_hour-1;
55 } else {
56 // time travel back in time may have impact on y/m/... > roundtrip required
57 time_t backOneHour = mktime(&c) - 60*60;
58 #ifndef _WIN32
59 localtime_r(&backOneHour, &c);
60 #else
61 localtime_s(&c, &backOneHour);
62 #endif
63
64 }
65
66 strftime(result, sizeof(result)*100, "%Y-%m-%d %H:%M:%S", &c);
67 } else {
68 strftime(result, sizeof(result)*100, "%Y-%m-%d %H:%M:%S", datetime);
69 }
70 return result;
71 }
72
datetimeToString(const time_t ts)73 std::string datetimeToString(const time_t ts)
74 {
75 char to[50];
76 datetimeTo(localtime(&ts), to);
77 return string{to};
78 }
79
datetimeSeconds(struct tm * datetime)80 time_t datetimeSeconds(struct tm* datetime)
81 {
82 return mktime(datetime);
83 }
84
85 enum class Pretty
86 {
87 TODAY,
88 THIS_WEEK,
89 THIS_YEAR,
90 LONG_TIME_AGO
91 };
92
datetimeToPrettyHtml(const time_t ts)93 std::string datetimeToPrettyHtml(const time_t ts)
94 {
95 return datetimeToPrettyHtml(&ts);
96 }
97
98 constexpr time_t SIX_DAYS = 60 * 60 * 24 * 6;
datetimeToPrettyHtml(const time_t * seconds)99 std::string datetimeToPrettyHtml(const time_t* seconds)
100 {
101 time_t now;
102 time(&now);
103
104 tm tsS = *localtime(seconds);
105 tm* nowS = localtime(&now);
106
107 Pretty pretty = Pretty::LONG_TIME_AGO;
108
109 if(tsS.tm_year==nowS->tm_year) {
110 if(tsS.tm_mon==nowS->tm_mon && tsS.tm_mday==nowS->tm_mday) {
111 pretty = Pretty::TODAY;
112 } else {
113 if(now-*seconds < SIX_DAYS && tsS.tm_wday<=nowS->tm_wday) {
114 pretty = Pretty::THIS_WEEK;
115 } else {
116 pretty = Pretty::THIS_YEAR;
117 }
118 }
119 } else {
120 if(now-*seconds < SIX_DAYS) {
121 pretty = Pretty::THIS_WEEK;
122 }
123 }
124
125 const char *background;
126 char text[50];
127 switch(pretty) {
128 case Pretty::LONG_TIME_AGO:
129 background = "BBBBBB";
130 strftime(text, sizeof(text), "%Y", &tsS);
131 break;
132 case Pretty::THIS_YEAR:
133 background = "888888";
134 strftime(text, sizeof(text), "%b %e", &tsS);
135 break;
136 case Pretty::THIS_WEEK:
137 background= "555555";
138 strftime(text, sizeof(text), "%A", &tsS);
139 break;
140 // IMPROVE this month
141 case Pretty::TODAY:
142 background = "000000";
143 strftime(text, sizeof(text), "%R", &tsS);
144 break;
145 }
146
147 // note that long timestamp is added to the HTML - it is convenient for parsing/sorting/processing
148 std::string result;
149 result =
150 "<div title='" +
151 to_stringl(*seconds) +
152 "' style='background-color: #" +
153 string(background) +
154 "; color: #ffffff; text-align: center; white-space: pre;'>" + " " +
155 string(text) +
156 " " + "</div>";
157 return result;
158 }
159
160 } // m8r namespace
161
162