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