1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2015-2019 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22 /*
23 * BAREOS floating point time and date routines -- John Walker
24 *
25 * Later double precision integer time/date routines -- Kern Sibbald
26 *
27 */
28
29 /* Concerning times. There are a number of differnt time standards
30 * in BAREOS (fdate_t, ftime_t, time_t (Unix standard), btime_t, and
31 * utime_t). fdate_t and ftime_t are deprecated and should no longer
32 * be used, and in general, Unix time time_t should no longer be used,
33 * it is being phased out.
34 *
35 * Epoch is the base of Unix time in seconds (time_t, ...)
36 * and is 1 Jan 1970 at 0:0 UTC
37 *
38 * The major two times that should be left are:
39 * btime_t (64 bit integer in microseconds base Epoch)
40 * utime_t (64 bit integer in seconds base Epoch)
41 */
42
43 #include "include/bareos.h"
44 #include <math.h>
45
Blocaltime(const time_t * time,struct tm * tm)46 void Blocaltime(const time_t* time, struct tm* tm)
47 {
48 /* ***FIXME**** localtime_r() should be user configurable */
49 (void)localtime_r(time, tm);
50 }
51
52 /*
53 * Formatted time for user display: dd-Mon-yyyy hh:mm
54 */
bstrftime(char * dt,int maxlen,utime_t utime,const char * fmt)55 char* bstrftime(char* dt, int maxlen, utime_t utime, const char* fmt)
56 {
57 time_t time = (time_t)utime;
58 struct tm tm;
59
60 Blocaltime(&time, &tm);
61 if (fmt) {
62 strftime(dt, maxlen, fmt, &tm);
63 } else {
64 strftime(dt, maxlen, "%d-%b-%Y %H:%M", &tm);
65 }
66
67 return dt;
68 }
69
70 /*
71 * Formatted time for user display: dd-Mon-yyyy hh:mm:ss
72 */
bstrftimes(char * dt,int maxlen,utime_t utime)73 char* bstrftimes(char* dt, int maxlen, utime_t utime)
74 {
75 return bstrftime(dt, maxlen, utime, "%d-%b-%Y %H:%M:%S");
76 }
77
78 /*
79 * Formatted time for user display: dd-Mon hh:mm
80 */
bstrftime_ny(char * dt,int maxlen,utime_t utime)81 char* bstrftime_ny(char* dt, int maxlen, utime_t utime)
82 {
83 return bstrftime(dt, maxlen, utime, "%d-%b %H:%M");
84 }
85
86 /*
87 * Formatted time for user display with weekday: weekday dd-Mon hh:mm
88 */
bstrftime_wd(char * dt,int maxlen,utime_t utime)89 char* bstrftime_wd(char* dt, int maxlen, utime_t utime)
90 {
91 return bstrftime(dt, maxlen, utime, "%a %d-%b-%Y %H:%M");
92 }
93
94 /*
95 * Formatted time for user display: dd-Mon-yy hh:mm (no century)
96 */
bstrftime_nc(char * dt,int maxlen,utime_t utime)97 char* bstrftime_nc(char* dt, int maxlen, utime_t utime)
98 {
99 char *p, *q;
100
101 /*
102 * NOTE! since the compiler complains about %y, I use %Y and cut the century
103 */
104 bstrftime(dt, maxlen, utime, "%d-%b-%Y %H:%M");
105
106 /*
107 * Overlay the century
108 */
109 p = dt + 7;
110 q = dt + 9;
111 while (*q) { *p++ = *q++; }
112 *p = 0;
113 return dt;
114 }
115
116 /*
117 * Unix time to standard time string yyyy-mm-dd hh:mm:ss
118 */
bstrutime(char * dt,int maxlen,utime_t utime)119 char* bstrutime(char* dt, int maxlen, utime_t utime)
120 {
121 return bstrftime(dt, maxlen, utime, "%Y-%m-%d %H:%M:%S");
122 }
123
124 /*
125 * Convert standard time string yyyy-mm-dd hh:mm:ss to Unix time
126 */
StrToUtime(const char * str)127 utime_t StrToUtime(const char* str)
128 {
129 struct tm tm;
130 time_t time;
131
132 /*
133 * Check for bad argument
134 */
135 if (!str || *str == 0) { return 0; }
136
137 if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
138 &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
139 != 6) {
140 return 0;
141 }
142 if (tm.tm_mon > 0) {
143 tm.tm_mon--;
144 } else {
145 return 0;
146 }
147 if (tm.tm_year >= 1900) {
148 tm.tm_year -= 1900;
149 } else {
150 return 0;
151 }
152 tm.tm_wday = tm.tm_yday = 0;
153 tm.tm_isdst = -1;
154 time = mktime(&tm);
155 if (time == -1) { time = 0; }
156 return (utime_t)time;
157 }
158
159
160 /*
161 * BAREOS's time (btime_t) is an unsigned 64 bit integer that contains
162 * the number of microseconds since Epoch Time (1 Jan 1970) UTC.
163 */
164
GetCurrentBtime()165 btime_t GetCurrentBtime()
166 {
167 struct timeval tv;
168 if (gettimeofday(&tv, NULL) != 0) {
169 tv.tv_sec = (long)time(NULL); /* fall back to old method */
170 tv.tv_usec = 0;
171 }
172 return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec;
173 }
174
175 /*
176 * Convert btime to Unix time
177 */
BtimeToUnix(btime_t bt)178 time_t BtimeToUnix(btime_t bt) { return (time_t)(bt / 1000000); }
179
180 /*
181 * Convert btime to utime
182 */
BtimeToUtime(btime_t bt)183 utime_t BtimeToUtime(btime_t bt) { return (utime_t)(bt / 1000000); }
184
185 /*
186 * Return the week of the month, base 0 (wom)
187 * given tm_mday and tm_wday. Value returned
188 * can be from 0 to 4 => week1, ... week5
189 */
tm_wom(int mday,int wday)190 int tm_wom(int mday, int wday)
191 {
192 int fs; /* first sunday */
193 int wom;
194
195 fs = (mday % 7) - wday;
196 if (fs <= 0) { fs += 7; }
197 if (mday <= fs) { return 0; }
198 wom = 1 + (mday - fs - 1) / 7;
199
200 return wom;
201 }
202
203 /*
204 * Given a Unix date return the week of the year.
205 * The returned value can be 0-53. Officially
206 * the weeks are numbered from 1 to 53 where week1
207 * is the week in which the first Thursday of the
208 * year occurs (alternatively, the week which contains
209 * the 4th of January). We return 0, if the week of the
210 * year does not fall in the current year.
211 */
TmWoy(time_t stime)212 int TmWoy(time_t stime)
213 {
214 int woy, fty, tm_yday;
215 time_t time4;
216 struct tm tm;
217
218 memset(&tm, 0, sizeof(struct tm));
219 Blocaltime(&stime, &tm);
220 tm_yday = tm.tm_yday;
221 tm.tm_mon = 0;
222 tm.tm_mday = 4;
223 tm.tm_isdst = 0; /* 4 Jan is not DST */
224 time4 = mktime(&tm);
225 Blocaltime(&time4, &tm);
226 fty = 1 - tm.tm_wday;
227 if (fty <= 0) { fty += 7; }
228 woy = tm_yday - fty + 4;
229 if (woy < 0) { return 0; }
230 return 1 + woy / 7;
231 }
232
233 /*
234 * Deprecated. Do not use.
235 */
get_current_time(struct date_time * dt)236 void get_current_time(struct date_time* dt)
237 {
238 struct tm tm;
239 time_t now;
240
241 now = time(NULL);
242 (void)gmtime_r(&now, &tm);
243 Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
244 tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
245 TmEncode(dt, &tm);
246 Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number,
247 dt->julian_day_fraction);
248 TmDecode(dt, &tm);
249 Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
250 tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
251 }
252
253
254 /* DateEncode -- Encode civil date as a Julian day number. */
255
256 /* Deprecated. Do not use. */
DateEncode(uint32_t year,uint8_t month,uint8_t day)257 fdate_t DateEncode(uint32_t year, uint8_t month, uint8_t day)
258 {
259 /* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 */
260
261 int32_t a, b, m;
262 uint32_t y;
263
264 ASSERT(month < 13);
265 ASSERT(day > 0 && day < 32);
266
267 m = month;
268 y = year;
269
270 if (m <= 2) {
271 y--;
272 m += 12;
273 }
274
275 /* Determine whether date is in Julian or Gregorian calendar based on
276 canonical date of calendar reform. */
277
278 if ((year < 1582)
279 || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
280 b = 0;
281 } else {
282 a = ((int)(y / 100));
283 b = 2 - a + (a / 4);
284 }
285
286 return (((int32_t)(365.25 * (y + 4716))) + ((int)(30.6001 * (m + 1))) + day
287 + b - 1524.5);
288 }
289
290 /* TimeEncode -- Encode time from hours, minutes, and seconds
291 into a fraction of a day. */
292
293 /* Deprecated. Do not use. */
TimeEncode(uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)294 ftime_t TimeEncode(uint8_t hour,
295 uint8_t minute,
296 uint8_t second,
297 float32_t second_fraction)
298 {
299 ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
300 return (ftime_t)(((second + 60L * (minute + 60L * hour)) / 86400.0))
301 + second_fraction;
302 }
303
304 /* date_time_encode -- Set day number and fraction from date
305 and time. */
306
307 /* Deprecated. Do not use. */
date_time_encode(struct date_time * dt,uint32_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)308 void date_time_encode(struct date_time* dt,
309 uint32_t year,
310 uint8_t month,
311 uint8_t day,
312 uint8_t hour,
313 uint8_t minute,
314 uint8_t second,
315 float32_t second_fraction)
316 {
317 dt->julian_day_number = DateEncode(year, month, day);
318 dt->julian_day_fraction = TimeEncode(hour, minute, second, second_fraction);
319 }
320
321 /* DateDecode -- Decode a Julian day number into civil date. */
322
323 /* Deprecated. Do not use. */
DateDecode(fdate_t date,uint32_t * year,uint8_t * month,uint8_t * day)324 void DateDecode(fdate_t date, uint32_t* year, uint8_t* month, uint8_t* day)
325 {
326 fdate_t z, f, a, alpha, b, c, d, e;
327
328 date += 0.5;
329 z = floor(date);
330 f = date - z;
331
332 if (z < 2299161.0) {
333 a = z;
334 } else {
335 alpha = floor((z - 1867216.25) / 36524.25);
336 a = z + 1 + alpha - floor(alpha / 4);
337 }
338
339 b = a + 1524;
340 c = floor((b - 122.1) / 365.25);
341 d = floor(365.25 * c);
342 e = floor((b - d) / 30.6001);
343
344 *day = (uint8_t)(b - d - floor(30.6001 * e) + f);
345 *month = (uint8_t)((e < 14) ? (e - 1) : (e - 13));
346 *year = (uint32_t)((*month > 2) ? (c - 4716) : (c - 4715));
347 }
348
349 /* TimeDecode -- Decode a day fraction into civil time. */
350
351 /* Deprecated. Do not use. */
TimeDecode(ftime_t time,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)352 void TimeDecode(ftime_t time,
353 uint8_t* hour,
354 uint8_t* minute,
355 uint8_t* second,
356 float32_t* second_fraction)
357 {
358 uint32_t ij;
359
360 ij = (uint32_t)((time - floor(time)) * 86400.0);
361 *hour = (uint8_t)(ij / 3600L);
362 *minute = (uint8_t)((ij / 60L) % 60L);
363 *second = (uint8_t)(ij % 60L);
364 if (second_fraction != NULL) {
365 *second_fraction = (float32_t)(time - floor(time));
366 }
367 }
368
369 /* date_time_decode -- Decode a Julian day and day fraction
370 into civil date and time. */
371
372 /* Deprecated. Do not use. */
date_time_decode(struct date_time * dt,uint32_t * year,uint8_t * month,uint8_t * day,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)373 void date_time_decode(struct date_time* dt,
374 uint32_t* year,
375 uint8_t* month,
376 uint8_t* day,
377 uint8_t* hour,
378 uint8_t* minute,
379 uint8_t* second,
380 float32_t* second_fraction)
381 {
382 DateDecode(dt->julian_day_number, year, month, day);
383 TimeDecode(dt->julian_day_fraction, hour, minute, second, second_fraction);
384 }
385
386 /* TmEncode -- Encode a civil date and time from a tm structure
387 * to a Julian day and day fraction.
388 */
389
390 /* Deprecated. Do not use. */
TmEncode(struct date_time * dt,struct tm * tm)391 void TmEncode(struct date_time* dt, struct tm* tm)
392 {
393 uint32_t year;
394 uint8_t month, day, hour, minute, second;
395
396 year = tm->tm_year + 1900;
397 month = tm->tm_mon + 1;
398 day = tm->tm_mday;
399 hour = tm->tm_hour;
400 minute = tm->tm_min;
401 second = tm->tm_sec;
402 dt->julian_day_number = DateEncode(year, month, day);
403 dt->julian_day_fraction = TimeEncode(hour, minute, second, 0.0);
404 }
405
406
407 /* TmDecode -- Decode a Julian day and day fraction
408 into civil date and time in tm structure */
409
410 /* Deprecated. Do not use. */
TmDecode(struct date_time * dt,struct tm * tm)411 void TmDecode(struct date_time* dt, struct tm* tm)
412 {
413 uint32_t year;
414 uint8_t month, day, hour, minute, second;
415
416 DateDecode(dt->julian_day_number, &year, &month, &day);
417 TimeDecode(dt->julian_day_fraction, &hour, &minute, &second, NULL);
418 tm->tm_year = year - 1900;
419 tm->tm_mon = month - 1;
420 tm->tm_mday = day;
421 tm->tm_hour = hour;
422 tm->tm_min = minute;
423 tm->tm_sec = second;
424 }
425
426
427 /* DateTimeCompare -- Compare two dates and times and return
428 the relationship as follows:
429
430 -1 dt1 < dt2
431 0 dt1 = dt2
432 1 dt1 > dt2
433 */
434
435 /* Deprecated. Do not use. */
DateTimeCompare(struct date_time * dt1,struct date_time * dt2)436 int DateTimeCompare(struct date_time* dt1, struct date_time* dt2)
437 {
438 if (dt1->julian_day_number == dt2->julian_day_number) {
439 if (dt1->julian_day_fraction == dt2->julian_day_fraction) { return 0; }
440 return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
441 }
442 return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
443 }
444