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