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