1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2015-2015 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) {
112 *p++ = *q++;
113 }
114 *p = 0;
115 return dt;
116 }
117
118 /*
119 * Unix time to standard time string yyyy-mm-dd hh:mm:ss
120 */
bstrutime(char * dt,int maxlen,utime_t utime)121 char *bstrutime(char *dt, int maxlen, utime_t utime)
122 {
123 return bstrftime(dt, maxlen, utime, "%Y-%m-%d %H:%M:%S");
124 }
125
126 /*
127 * Convert standard time string yyyy-mm-dd hh:mm:ss to Unix time
128 */
StrToUtime(const char * str)129 utime_t StrToUtime(const char *str)
130 {
131 struct tm tm;
132 time_t time;
133
134 /*
135 * Check for bad argument
136 */
137 if (!str || *str == 0) {
138 return 0;
139 }
140
141 if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
142 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
143 return 0;
144 }
145 if (tm.tm_mon > 0) {
146 tm.tm_mon--;
147 } else {
148 return 0;
149 }
150 if (tm.tm_year >= 1900) {
151 tm.tm_year -= 1900;
152 } else {
153 return 0;
154 }
155 tm.tm_wday = tm.tm_yday = 0;
156 tm.tm_isdst = -1;
157 time = mktime(&tm);
158 if (time == -1) {
159 time = 0;
160 }
161 return (utime_t)time;
162 }
163
164
165 /*
166 * BAREOS's time (btime_t) is an unsigned 64 bit integer that contains
167 * the number of microseconds since Epoch Time (1 Jan 1970) UTC.
168 */
169
GetCurrentBtime()170 btime_t GetCurrentBtime()
171 {
172 struct timeval tv;
173 if (gettimeofday(&tv, NULL) != 0) {
174 tv.tv_sec = (long)time(NULL); /* fall back to old method */
175 tv.tv_usec = 0;
176 }
177 return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec;
178 }
179
180 /*
181 * Convert btime to Unix time
182 */
BtimeToUnix(btime_t bt)183 time_t BtimeToUnix(btime_t bt)
184 {
185 return (time_t)(bt/1000000);
186 }
187
188 /*
189 * Convert btime to utime
190 */
BtimeToUtime(btime_t bt)191 utime_t BtimeToUtime(btime_t bt)
192 {
193 return (utime_t)(bt/1000000);
194 }
195
196 /*
197 * Return the week of the month, base 0 (wom)
198 * given tm_mday and tm_wday. Value returned
199 * can be from 0 to 4 => week1, ... week5
200 */
tm_wom(int mday,int wday)201 int tm_wom(int mday, int wday)
202 {
203 int fs; /* first sunday */
204 int wom;
205
206 fs = (mday%7) - wday;
207 if (fs <= 0) {
208 fs += 7;
209 }
210 if (mday <= fs) {
211 return 0;
212 }
213 wom = 1 + (mday - fs - 1) / 7;
214
215 return wom;
216 }
217
218 /*
219 * Given a Unix date return the week of the year.
220 * The returned value can be 0-53. Officially
221 * the weeks are numbered from 1 to 53 where week1
222 * is the week in which the first Thursday of the
223 * year occurs (alternatively, the week which contains
224 * the 4th of January). We return 0, if the week of the
225 * year does not fall in the current year.
226 */
TmWoy(time_t stime)227 int TmWoy(time_t stime)
228 {
229 int woy, fty, tm_yday;
230 time_t time4;
231 struct tm tm;
232
233 memset(&tm, 0, sizeof(struct tm));
234 Blocaltime(&stime, &tm);
235 tm_yday = tm.tm_yday;
236 tm.tm_mon = 0;
237 tm.tm_mday = 4;
238 tm.tm_isdst = 0; /* 4 Jan is not DST */
239 time4 = mktime(&tm);
240 Blocaltime(&time4, &tm);
241 fty = 1 - tm.tm_wday;
242 if (fty <= 0) {
243 fty += 7;
244 }
245 woy = tm_yday - fty + 4;
246 if (woy < 0) {
247 return 0;
248 }
249 return 1 + woy / 7;
250 }
251
252 /*
253 * Deprecated. Do not use.
254 */
get_current_time(struct date_time * dt)255 void get_current_time(struct date_time *dt)
256 {
257 struct tm tm;
258 time_t now;
259
260 now = time(NULL);
261 (void)gmtime_r(&now, &tm);
262 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,
263 tm.tm_hour, tm.tm_min, tm.tm_sec);
264 TmEncode(dt, &tm);
265 #ifdef DEBUG
266 Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number, dt->julian_day_fraction);
267 TmDecode(dt, &tm);
268 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,
269 tm.tm_hour, tm.tm_min, tm.tm_sec);
270 #endif
271 }
272
273
274 /* DateEncode -- Encode civil date as a Julian day number. */
275
276 /* Deprecated. Do not use. */
DateEncode(uint32_t year,uint8_t month,uint8_t day)277 fdate_t DateEncode(uint32_t year, uint8_t month, uint8_t day)
278 {
279
280 /* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 */
281
282 int32_t a, b, m;
283 uint32_t y;
284
285 ASSERT(month < 13);
286 ASSERT(day > 0 && day < 32);
287
288 m = month;
289 y = year;
290
291 if (m <= 2) {
292 y--;
293 m += 12;
294 }
295
296 /* Determine whether date is in Julian or Gregorian calendar based on
297 canonical date of calendar reform. */
298
299 if ((year < 1582) || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
300 b = 0;
301 } else {
302 a = ((int) (y / 100));
303 b = 2 - a + (a / 4);
304 }
305
306 return (((int32_t) (365.25 * (y + 4716))) + ((int) (30.6001 * (m + 1))) +
307 day + b - 1524.5);
308 }
309
310 /* TimeEncode -- Encode time from hours, minutes, and seconds
311 into a fraction of a day. */
312
313 /* Deprecated. Do not use. */
TimeEncode(uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)314 ftime_t TimeEncode(uint8_t hour, uint8_t minute, uint8_t second,
315 float32_t second_fraction)
316 {
317 ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
318 return (ftime_t) (((second + 60L * (minute + 60L * hour)) / 86400.0)) +
319 second_fraction;
320 }
321
322 /* date_time_encode -- Set day number and fraction from date
323 and time. */
324
325 /* 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)326 void date_time_encode(struct date_time *dt,
327 uint32_t year, uint8_t month, uint8_t day,
328 uint8_t hour, uint8_t minute, uint8_t second,
329 float32_t second_fraction)
330 {
331 dt->julian_day_number = DateEncode(year, month, day);
332 dt->julian_day_fraction = TimeEncode(hour, minute, second, second_fraction);
333 }
334
335 /* DateDecode -- Decode a Julian day number into civil date. */
336
337 /* Deprecated. Do not use. */
DateDecode(fdate_t date,uint32_t * year,uint8_t * month,uint8_t * day)338 void DateDecode(fdate_t date, uint32_t *year, uint8_t *month,
339 uint8_t *day)
340 {
341 fdate_t z, f, a, alpha, b, c, d, e;
342
343 date += 0.5;
344 z = floor(date);
345 f = date - z;
346
347 if (z < 2299161.0) {
348 a = z;
349 } else {
350 alpha = floor((z - 1867216.25) / 36524.25);
351 a = z + 1 + alpha - floor(alpha / 4);
352 }
353
354 b = a + 1524;
355 c = floor((b - 122.1) / 365.25);
356 d = floor(365.25 * c);
357 e = floor((b - d) / 30.6001);
358
359 *day = (uint8_t) (b - d - floor(30.6001 * e) + f);
360 *month = (uint8_t) ((e < 14) ? (e - 1) : (e - 13));
361 *year = (uint32_t) ((*month > 2) ? (c - 4716) : (c - 4715));
362 }
363
364 /* TimeDecode -- Decode a day fraction into civil time. */
365
366 /* Deprecated. Do not use. */
TimeDecode(ftime_t time,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)367 void TimeDecode(ftime_t time, uint8_t *hour, uint8_t *minute,
368 uint8_t *second, float32_t *second_fraction)
369 {
370 uint32_t ij;
371
372 ij = (uint32_t) ((time - floor(time)) * 86400.0);
373 *hour = (uint8_t) (ij / 3600L);
374 *minute = (uint8_t) ((ij / 60L) % 60L);
375 *second = (uint8_t) (ij % 60L);
376 if (second_fraction != NULL) {
377 *second_fraction = (float32_t)(time - floor(time));
378 }
379 }
380
381 /* date_time_decode -- Decode a Julian day and day fraction
382 into civil date and time. */
383
384 /* 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)385 void date_time_decode(struct date_time *dt,
386 uint32_t *year, uint8_t *month, uint8_t *day,
387 uint8_t *hour, uint8_t *minute, uint8_t *second,
388 float32_t *second_fraction)
389 {
390 DateDecode(dt->julian_day_number, year, month, day);
391 TimeDecode(dt->julian_day_fraction, hour, minute, second, second_fraction);
392 }
393
394 /* TmEncode -- Encode a civil date and time from a tm structure
395 * to a Julian day and day fraction.
396 */
397
398 /* Deprecated. Do not use. */
TmEncode(struct date_time * dt,struct tm * tm)399 void TmEncode(struct date_time *dt,
400 struct tm *tm)
401 {
402 uint32_t year;
403 uint8_t month, day, hour, minute, second;
404
405 year = tm->tm_year + 1900;
406 month = tm->tm_mon + 1;
407 day = tm->tm_mday;
408 hour = tm->tm_hour;
409 minute = tm->tm_min;
410 second = tm->tm_sec;
411 dt->julian_day_number = DateEncode(year, month, day);
412 dt->julian_day_fraction = TimeEncode(hour, minute, second, 0.0);
413 }
414
415
416 /* TmDecode -- Decode a Julian day and day fraction
417 into civil date and time in tm structure */
418
419 /* Deprecated. Do not use. */
TmDecode(struct date_time * dt,struct tm * tm)420 void TmDecode(struct date_time *dt,
421 struct tm *tm)
422 {
423 uint32_t year;
424 uint8_t month, day, hour, minute, second;
425
426 DateDecode(dt->julian_day_number, &year, &month, &day);
427 TimeDecode(dt->julian_day_fraction, &hour, &minute, &second, NULL);
428 tm->tm_year = year - 1900;
429 tm->tm_mon = month - 1;
430 tm->tm_mday = day;
431 tm->tm_hour = hour;
432 tm->tm_min = minute;
433 tm->tm_sec = second;
434 }
435
436
437 /* DateTimeCompare -- Compare two dates and times and return
438 the relationship as follows:
439
440 -1 dt1 < dt2
441 0 dt1 = dt2
442 1 dt1 > dt2
443 */
444
445 /* Deprecated. Do not use. */
DateTimeCompare(struct date_time * dt1,struct date_time * dt2)446 int DateTimeCompare(struct date_time *dt1, struct date_time *dt2)
447 {
448 if (dt1->julian_day_number == dt2->julian_day_number) {
449 if (dt1->julian_day_fraction == dt2->julian_day_fraction) {
450 return 0;
451 }
452 return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
453 }
454 return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
455 }
456