1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Bacula floating point time and date routines -- John Walker
21 *
22 * Later double precision integer time/date routines -- Kern Sibbald
23 *
24 */
25
26 /*
27 * Concerning times. There are a number of different time standards
28 * in Bacula (fdate_t, ftime_t, time_t (Unix standard), btime_t, and
29 * utime_t). fdate_t and ftime_t are deprecated and should no longer
30 * be used, and in general, Unix time time_t should no longer be used,
31 * it is being phased out.
32 *
33 * Epoch is the base of Unix time in seconds (time_t, ...)
34 * and is 1 Jan 1970 at 0:0 UTC
35 *
36 * The major two times that should be left are:
37 * btime_t (64 bit integer in microseconds base Epoch)
38 * utime_t (64 bit integer in seconds base Epoch)
39 */
40
41 #include "bacula.h"
42 #include <math.h>
43
44 /* Formatted time for catalog: yyymmddhhmmss */
bstrftime_c(char * dt,int maxlen,utime_t utime)45 char *bstrftime_c(char *dt, int maxlen, utime_t utime)
46 {
47 time_t time = (time_t)utime;
48 struct tm tm;
49
50 /* ***FIXME**** the format and localtime_r() should be user configurable */
51 (void)localtime_r(&time, &tm);
52 strftime(dt, maxlen, "%Y%m%d%H%m%S", &tm);
53 return dt;
54 }
55
56 /* Formatted time for user display: dd-Mon-yyyy hh:mm */
bstrftime(char * dt,int maxlen,utime_t utime)57 char *bstrftime(char *dt, int maxlen, utime_t utime)
58 {
59 time_t time = (time_t)utime;
60 struct tm tm;
61
62 /* ***FIXME**** the format and localtime_r() should be user configurable */
63 (void)localtime_r(&time, &tm);
64 strftime(dt, maxlen, "%d-%b-%Y %H:%M", &tm);
65 return dt;
66 }
67
bstrftimes_na(char * dt,int maxlen,utime_t utime)68 char *bstrftimes_na(char *dt, int maxlen, utime_t utime)
69 {
70 if (utime == 0) {
71 return bstrncpy(dt, "", maxlen);
72 } else {
73 return bstrftimes(dt, maxlen, utime);
74 }
75 }
76
77 /* Formatted time for user display: dd-Mon-yyyy hh:mm:ss */
bstrftimes(char * dt,int maxlen,utime_t utime)78 char *bstrftimes(char *dt, int maxlen, utime_t utime)
79 {
80 time_t time = (time_t)utime;
81 struct tm tm;
82
83 /* ***FIXME**** the format and localtime_r() should be user configurable */
84 (void)localtime_r(&time, &tm);
85 strftime(dt, maxlen, "%d-%b-%Y %H:%M:%S", &tm);
86 return dt;
87 }
88
89 /* Formatted time with day name for user display: dd-Mon hh:mm */
bstrftime_dn(char * dt,int maxlen,utime_t utime)90 char *bstrftime_dn(char *dt, int maxlen, utime_t utime)
91 {
92 time_t time = (time_t)utime;
93 struct tm tm;
94
95 /* ***FIXME**** the format and localtime_r() should be user configurable */
96 (void)localtime_r(&time, &tm);
97 strftime(dt, maxlen, "%a %d-%b %H:%M", &tm);
98 return dt;
99 }
100
101 /* Formatted time (no year) for user display: dd-Mon hh:mm */
bstrftime_ny(char * dt,int maxlen,utime_t utime)102 char *bstrftime_ny(char *dt, int maxlen, utime_t utime)
103 {
104 time_t time = (time_t)utime;
105 struct tm tm;
106
107 /* ***FIXME**** the format and localtime_r() should be user configurable */
108 (void)localtime_r(&time, &tm);
109 strftime(dt, maxlen, "%d-%b %H:%M", &tm);
110 return dt;
111 }
112
113
114 /* Formatted time for user display: dd-Mon-yy hh:mm (no century) */
bstrftime_nc(char * dt,int maxlen,utime_t utime)115 char *bstrftime_nc(char *dt, int maxlen, utime_t utime)
116 {
117 time_t time = (time_t)utime;
118 struct tm tm;
119 char *p, *q;
120
121 /* ***FIXME**** the format and localtime_r() should be user configurable */
122 (void)localtime_r(&time, &tm);
123 /* NOTE! since the compiler complains about %y, I use %y and cut the century */
124 strftime(dt, maxlen, "%d-%b-%Y %H:%M", &tm);
125 /* overlay the century */
126 p = dt+7;
127 q = dt+9;
128 while (*q) {
129 *p++ = *q++;
130 }
131 *p = 0;
132 return dt;
133 }
134
135
136 /* Unix time to standard time string yyyy-mm-dd hh:mm:ss */
bstrutime(char * dt,int maxlen,utime_t utime)137 char *bstrutime(char *dt, int maxlen, utime_t utime)
138 {
139 time_t time = (time_t)utime;
140 struct tm tm;
141 (void)localtime_r(&time, &tm);
142 strftime(dt, maxlen, "%Y-%m-%d %H:%M:%S", &tm);
143 return dt;
144 }
145
146 /* Convert standard time string yyyy-mm-dd hh:mm:ss to Unix time */
str_to_utime(char * str)147 utime_t str_to_utime(char *str)
148 {
149 struct tm tm;
150 time_t time;
151
152 /* Minimal check for bad argument */
153 if (!str || *str == 0 || (strlen(str) != 19) ||
154 (str[4] != '-') || (str[7] != '-') ||
155 (str[13] != ':') || (str[16] != ':')) {
156 return 0;
157 }
158
159 if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year,
160 &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
161 return 0;
162 }
163 if (tm.tm_mon > 0) {
164 tm.tm_mon--;
165 } else {
166 return 0;
167 }
168 if (tm.tm_year >= 1900) {
169 tm.tm_year -= 1900;
170 } else {
171 return 0;
172 }
173 tm.tm_wday = tm.tm_yday = 0;
174 tm.tm_isdst = -1;
175 time = mktime(&tm);
176 if (time == -1) {
177 time = 0;
178 }
179 return (utime_t)time;
180 }
181
182
183 /*
184 * Bacula's time (btime_t) is an unsigned 64 bit integer that contains
185 * the number of microseconds since Epoch Time (1 Jan 1970) UTC.
186 */
187
get_current_btime()188 btime_t get_current_btime()
189 {
190 struct timeval tv;
191 if (gettimeofday(&tv, NULL) != 0) {
192 tv.tv_sec = (long)time(NULL); /* fall back to old method */
193 tv.tv_usec = 0;
194 }
195 return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec;
196 }
197
198 /* Convert btime to Unix time */
btime_to_unix(btime_t bt)199 time_t btime_to_unix(btime_t bt)
200 {
201 return (time_t)(bt/1000000);
202 }
203
204 /* Convert btime to utime */
btime_to_utime(btime_t bt)205 utime_t btime_to_utime(btime_t bt)
206 {
207 return (utime_t)(bt/1000000);
208 }
209
210 /*
211 * Definition of a leap year from Wikipedia.
212 * I knew it anyway but better check.
213 */
is_leap_year(int year)214 static bool is_leap_year(int year)
215 {
216 if (year % 400 == 0) return true;
217 if (year % 100 == 0) return false;
218 if (year % 4 == 0) return true;
219 return false;
220 }
221
222 /*
223 * Return the last day of the month, base 0
224 * month=0-11, year is actual year
225 * ldom is base 0
226 */
tm_ldom(int month,int year)227 int tm_ldom(int month, int year)
228 { /* jan feb mar apr may jun jul aug sep oct nov dec */
229 static int dom[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
230
231 if (is_leap_year(year) && month == 1) return 28;
232 return dom[month] - 1;
233 }
234
235 /*
236 * Return the week of the month, base 0 (wom)
237 * given tm_mday and tm_wday. Value returned
238 * can be from 0 to 5 => week1, ... week6
239 */
tm_wom(int mday,int wday)240 int tm_wom(int mday, int wday)
241 {
242 int fs; /* first sunday */
243 fs = (mday%7) - wday;
244 if (fs <= 0) {
245 fs += 7;
246 }
247 if (mday <= fs) {
248 // Dmsg3(100, "mday=%d wom=0 wday=%d <= fs=%d\n", mday, wday, fs);
249 return 0;
250 }
251 int wom = 1 + (mday - fs - 1) / 7;
252 // Dmsg4(100, "mday=%d wom=%d wday=%d fs=%d\n", mday, wom, wday, fs);
253 return wom;
254 }
255
256 /*
257 * Given a Unix date return the week of the year.
258 * The returned value can be 0-53. Officially
259 * the weeks are numbered from 1 to 53 where week1
260 * is the week in which the first Thursday of the
261 * year occurs (alternatively, the week which contains
262 * the 4th of January). We return 0, if the week of the
263 * year does not fall in the current year.
264 */
tm_woy(time_t stime)265 int tm_woy(time_t stime)
266 {
267 int woy, fty, tm_yday;
268 time_t time4;
269 struct tm tm;
270
271 memset(&tm, 0, sizeof(struct tm));
272 (void)localtime_r(&stime, &tm);
273 tm_yday = tm.tm_yday;
274 tm.tm_mon = 0;
275 tm.tm_mday = 4;
276 tm.tm_isdst = 0; /* 4 Jan is not DST */
277 time4 = mktime(&tm);
278 (void)localtime_r(&time4, &tm);
279 fty = 1 - tm.tm_wday;
280 if (fty <= 0) {
281 fty += 7;
282 }
283 woy = tm_yday - fty + 4;
284 if (woy < 0) {
285 return 0;
286 }
287 return 1 + woy / 7;
288 }
289
290 /* Deprecated. Do not use. */
get_current_time(struct date_time * dt)291 void get_current_time(struct date_time *dt)
292 {
293 struct tm tm;
294 time_t now;
295
296 now = time(NULL);
297 (void)gmtime_r(&now, &tm);
298 Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900,
299 tm.tm_hour, tm.tm_min, tm.tm_sec);
300 tm_encode(dt, &tm);
301 #ifdef DEBUG
302 Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number, dt->julian_day_fraction);
303 tm_decode(dt, &tm);
304 Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900,
305 tm.tm_hour, tm.tm_min, tm.tm_sec);
306 #endif
307 }
308
309
310
311 /* date_encode -- Encode civil date as a Julian day number. */
312 /* Deprecated. Do not use. */
date_encode(uint32_t year,uint8_t month,uint8_t day)313 fdate_t date_encode(uint32_t year, uint8_t month, uint8_t day)
314 {
315
316 /* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 */
317
318 int32_t a, b, m;
319 uint32_t y;
320
321 ASSERT(month < 13);
322 ASSERT(day > 0 && day < 32);
323
324 m = month;
325 y = year;
326
327 if (m <= 2) {
328 y--;
329 m += 12;
330 }
331
332 /* Determine whether date is in Julian or Gregorian calendar based on
333 canonical date of calendar reform. */
334
335 if ((year < 1582) || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
336 b = 0;
337 } else {
338 a = ((int) (y / 100));
339 b = 2 - a + (a / 4);
340 }
341
342 return (((int32_t) (365.25 * (y + 4716))) + ((int) (30.6001 * (m + 1))) +
343 day + b - 1524.5);
344 }
345
346 /* time_encode -- Encode time from hours, minutes, and seconds
347 into a fraction of a day. */
348
349 /* Deprecated. Do not use. */
time_encode(uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)350 ftime_t time_encode(uint8_t hour, uint8_t minute, uint8_t second,
351 float32_t second_fraction)
352 {
353 ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
354 return (ftime_t) (((second + 60L * (minute + 60L * hour)) / 86400.0)) +
355 second_fraction;
356 }
357
358 /* date_time_encode -- Set day number and fraction from date
359 and time. */
360
361 /* 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)362 void date_time_encode(struct date_time *dt,
363 uint32_t year, uint8_t month, uint8_t day,
364 uint8_t hour, uint8_t minute, uint8_t second,
365 float32_t second_fraction)
366 {
367 dt->julian_day_number = date_encode(year, month, day);
368 dt->julian_day_fraction = time_encode(hour, minute, second, second_fraction);
369 }
370
371 /* date_decode -- Decode a Julian day number into civil date. */
372
373 /* Deprecated. Do not use. */
date_decode(fdate_t date,uint32_t * year,uint8_t * month,uint8_t * day)374 void date_decode(fdate_t date, uint32_t *year, uint8_t *month,
375 uint8_t *day)
376 {
377 fdate_t z, f, a, alpha, b, c, d, e;
378
379 date += 0.5;
380 z = floor(date);
381 f = date - z;
382
383 if (z < 2299161.0) {
384 a = z;
385 } else {
386 alpha = floor((z - 1867216.25) / 36524.25);
387 a = z + 1 + alpha - floor(alpha / 4);
388 }
389
390 b = a + 1524;
391 c = floor((b - 122.1) / 365.25);
392 d = floor(365.25 * c);
393 e = floor((b - d) / 30.6001);
394
395 *day = (uint8_t) (b - d - floor(30.6001 * e) + f);
396 *month = (uint8_t) ((e < 14) ? (e - 1) : (e - 13));
397 *year = (uint32_t) ((*month > 2) ? (c - 4716) : (c - 4715));
398 }
399
400 /* time_decode -- Decode a day fraction into civil time. */
401
402 /* Deprecated. Do not use. */
time_decode(ftime_t time,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)403 void time_decode(ftime_t time, uint8_t *hour, uint8_t *minute,
404 uint8_t *second, float32_t *second_fraction)
405 {
406 uint32_t ij;
407
408 ij = (uint32_t) ((time - floor(time)) * 86400.0);
409 *hour = (uint8_t) (ij / 3600L);
410 *minute = (uint8_t) ((ij / 60L) % 60L);
411 *second = (uint8_t) (ij % 60L);
412 if (second_fraction != NULL) {
413 *second_fraction = (float32_t)(time - floor(time));
414 }
415 }
416
417 /* date_time_decode -- Decode a Julian day and day fraction
418 into civil date and time. */
419
420 /* 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)421 void date_time_decode(struct date_time *dt,
422 uint32_t *year, uint8_t *month, uint8_t *day,
423 uint8_t *hour, uint8_t *minute, uint8_t *second,
424 float32_t *second_fraction)
425 {
426 date_decode(dt->julian_day_number, year, month, day);
427 time_decode(dt->julian_day_fraction, hour, minute, second, second_fraction);
428 }
429
430 /* tm_encode -- Encode a civil date and time from a tm structure
431 * to a Julian day and day fraction.
432 */
433
434 /* Deprecated. Do not use. */
tm_encode(struct date_time * dt,struct tm * tm)435 void tm_encode(struct date_time *dt,
436 struct tm *tm)
437 {
438 uint32_t year;
439 uint8_t month, day, hour, minute, second;
440
441 year = tm->tm_year + 1900;
442 month = tm->tm_mon + 1;
443 day = tm->tm_mday;
444 hour = tm->tm_hour;
445 minute = tm->tm_min;
446 second = tm->tm_sec;
447 dt->julian_day_number = date_encode(year, month, day);
448 dt->julian_day_fraction = time_encode(hour, minute, second, 0.0);
449 }
450
451
452 /* tm_decode -- Decode a Julian day and day fraction
453 into civil date and time in tm structure */
454
455 /* Deprecated. Do not use. */
tm_decode(struct date_time * dt,struct tm * tm)456 void tm_decode(struct date_time *dt,
457 struct tm *tm)
458 {
459 uint32_t year;
460 uint8_t month, day, hour, minute, second;
461
462 date_decode(dt->julian_day_number, &year, &month, &day);
463 time_decode(dt->julian_day_fraction, &hour, &minute, &second, NULL);
464 tm->tm_year = year - 1900;
465 tm->tm_mon = month - 1;
466 tm->tm_mday = day;
467 tm->tm_hour = hour;
468 tm->tm_min = minute;
469 tm->tm_sec = second;
470 }
471
472
473 /* date_time_compare -- Compare two dates and times and return
474 the relationship as follows:
475
476 -1 dt1 < dt2
477 0 dt1 = dt2
478 1 dt1 > dt2
479 */
480
481 /* Deprecated. Do not use. */
date_time_compare(struct date_time * dt1,struct date_time * dt2)482 int date_time_compare(struct date_time *dt1, struct date_time *dt2)
483 {
484 if (dt1->julian_day_number == dt2->julian_day_number) {
485 if (dt1->julian_day_fraction == dt2->julian_day_fraction) {
486 return 0;
487 }
488 return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
489 }
490 return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
491 }
492