1 /* gettime.c - Wrapper for time functions
2 * Copyright (C) 1998, 2002, 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #ifdef HAVE_LANGINFO_H
31 static unsigned long timewarp
;
32 static enum { NORMAL
= 0, FROZEN
, FUTURE
, PAST
} timemode
;
34 /* Correction used to map to real Julian days. */
35 #define JD_DIFF 1721060L
38 /* Wrapper for the time(3). We use this here so we can fake the time
43 time_t current
= time (NULL
);
44 if (timemode
== NORMAL
)
46 else if (timemode
== FROZEN
)
48 else if (timemode
== FUTURE
)
49 return current
+ timewarp
;
51 return current
- timewarp
;
55 /* Return the current time (possibly faked) in ISO format. */
57 gnupg_get_isotime (gnupg_isotime_t timebuf
)
59 time_t atime
= gnupg_get_time ();
69 tp
= gmtime_r (&atime
, &tmbuf
);
73 snprintf (timebuf
, 16, "%04d%02d%02dT%02d%02d%02d",
74 1900 + tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
75 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
80 /* Set the time to NEWTIME so that gnupg_get_time returns a time
81 starting with this one. With FREEZE set to 1 the returned time
82 will never change. Just for completeness, a value of (time_t)-1
83 for NEWTIME gets you back to reality. Note that this is obviously
84 not thread-safe but this is not required. */
86 gnupg_set_time (time_t newtime
, int freeze
)
88 time_t current
= time (NULL
);
90 if ( newtime
== (time_t)-1 || current
== newtime
)
100 else if (newtime
> current
)
103 timewarp
= newtime
- current
;
108 timewarp
= current
- newtime
;
112 /* Returns true when we are in timewarp mode */
114 gnupg_faked_time_p (void)
120 /* This function is used by gpg because OpenPGP defines the timestamp
121 as an unsigned 32 bit value. */
123 make_timestamp (void)
125 time_t t
= gnupg_get_time ();
128 log_fatal ("gnupg_get_time() failed\n");
135 * Scan a date string and return a timestamp.
136 * The only supported format is "yyyy-mm-dd"
137 * Returns 0 for an invalid date.
140 scan_isodatestr( const char *string
)
142 int year
, month
, day
;
147 if( strlen(string
) != 10 || string
[4] != '-' || string
[7] != '-' )
149 for( i
=0; i
< 4; i
++ )
150 if( !digitp (string
+i
) )
152 if( !digitp (string
+5) || !digitp(string
+6) )
154 if( !digitp(string
+8) || !digitp(string
+9) )
157 month
= atoi(string
+5);
158 day
= atoi(string
+8);
159 /* some basic checks */
160 if( year
< 1970 || month
< 1 || month
> 12 || day
< 1 || day
> 31 )
162 memset( &tmbuf
, 0, sizeof tmbuf
);
164 tmbuf
.tm_mon
= month
-1;
165 tmbuf
.tm_year
= year
- 1900;
167 stamp
= mktime( &tmbuf
);
168 if( stamp
== (time_t)-1 )
173 /* Scan am ISO timestamp and return an Epoch based timestamp. The only
174 supported format is "yyyymmddThhmmss" delimited by white space, nul, a
175 colon or a comma. Returns (time_t)(-1) for an invalid string. */
177 isotime2epoch (const char *string
)
180 int year
, month
, day
, hour
, minu
, sec
;
186 for (s
=string
, i
=0; i
< 8; i
++, s
++)
191 for (s
++, i
=9; i
< 15; i
++, s
++)
194 if ( !(!*s
|| (isascii (*s
) && isspace(*s
)) || *s
== ':' || *s
== ','))
195 return (time_t)(-1); /* Wrong delimiter. */
197 year
= atoi_4 (string
);
198 month
= atoi_2 (string
+ 4);
199 day
= atoi_2 (string
+ 6);
200 hour
= atoi_2 (string
+ 9);
201 minu
= atoi_2 (string
+ 11);
202 sec
= atoi_2 (string
+ 13);
205 if (year
< 1970 || month
< 1 || month
> 12 || day
< 1 || day
> 31
206 || hour
> 23 || minu
> 59 || sec
> 61 )
209 memset (&tmbuf
, 0, sizeof tmbuf
);
212 tmbuf
.tm_hour
= hour
;
214 tmbuf
.tm_mon
= month
-1;
215 tmbuf
.tm_year
= year
- 1900;
217 return timegm (&tmbuf
);
221 /* Convert an Epoch time to an iso time stamp. */
223 epoch2isotime (gnupg_isotime_t timebuf
, time_t atime
)
233 tp
= gmtime_r (&atime
, &tmbuf
);
235 tp
= gmtime (&atime
);
237 snprintf (timebuf
, 16, "%04d%02d%02dT%02d%02d%02d",
238 1900 + tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
239 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
247 add_days_to_timestamp( u32 stamp
, u16 days
)
249 return stamp
+ days
*86400L;
254 * Return a string with a time value in the form: x Y, n D, n H
258 strtimevalue( u32 value
)
260 static char buffer
[30];
261 unsigned int years
, days
, hours
, minutes
;
264 minutes
= value
% 60;
272 sprintf(buffer
,"%uy%ud%uh%um", years
, days
, hours
, minutes
);
276 return strchr( buffer
, 'y' ) + 1;
277 return strchr( buffer
, 'd' ) + 1;
282 * Note: this function returns GMT
285 strtimestamp( u32 stamp
)
287 static char buffer
[11+5];
289 time_t atime
= stamp
;
292 strcpy (buffer
, "????" "-??" "-??");
295 tp
= gmtime( &atime
);
296 sprintf(buffer
,"%04d-%02d-%02d",
297 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
);
304 * Note: this function returns GMT
307 isotimestamp (u32 stamp
)
309 static char buffer
[25+5];
311 time_t atime
= stamp
;
315 strcpy (buffer
, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
319 tp
= gmtime ( &atime
);
320 sprintf (buffer
,"%04d-%02d-%02d %02d:%02d:%02d",
321 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
322 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
329 * Note: this function returns local time
332 asctimestamp( u32 stamp
)
334 static char buffer
[50];
335 #if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
339 time_t atime
= stamp
;
342 strcpy (buffer
, "????" "-??" "-??");
346 tp
= localtime( &atime
);
348 #if defined(HAVE_NL_LANGINFO)
349 mem2str( fmt
, nl_langinfo(D_T_FMT
), DIM(fmt
)-3 );
350 if( strstr( fmt
, "%Z" ) == NULL
)
352 /* NOTE: gcc -Wformat-noliteral will complain here. I have
353 found no way to suppress this warning .*/
354 strftime (buffer
, DIM(buffer
)-1, fmt
, tp
);
356 /* FIXME: we should check whether the locale appends a " %Z"
357 * These locales from glibc don't put the " %Z":
358 * fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
360 strftime( buffer
, DIM(buffer
)-1, "%c %Z", tp
);
362 buffer
[DIM(buffer
)-1] = 0;
364 mem2str( buffer
, asctime(tp
), DIM(buffer
) );
372 days_per_year (int y
)
380 return s
? 366 : 365;
384 days_per_month (int y
, int m
)
390 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
398 case 4: case 6: case 9: case 11:
405 /* Convert YEAR, MONTH and DAY into the Julian date. We assume that
406 it is already noon. We do not support dates before 1582-10-15. */
408 date2jd (int year
, int month
, int day
)
412 jd
= 365L * year
+ 31 * (month
-1) + day
+ JD_DIFF
;
416 jd
-= (4 * month
+ 23) / 10;
418 jd
+= year
/ 4 - ((year
/ 100 + 1) *3) / 4;
423 /* Convert a Julian date back to YEAR, MONTH and DAY. Return day of
424 the year or 0 on error. This function uses some more or less
425 arbitrary limits, most important is that days before 1582 are not
428 jd2date (unsigned long jd
, int *year
, int *month
, int *day
)
435 if (jd
< 1721425 || jd
> 2843085)
438 y
= (jd
- JD_DIFF
) / 366;
441 while ((delta
= jd
- date2jd (y
, m
, d
)) > days_per_year (y
))
444 m
= (delta
/ 31) + 1;
445 while( (delta
= jd
- date2jd (y
, m
, d
)) > days_per_month (y
,m
))
453 if (d
> days_per_month (y
, m
))
471 return (jd
- date2jd (y
, 1, 1)) + 1;
475 /* Check that the 15 bytes in ATIME represent a valid ISO time. Note
476 that this function does not expect a string but a plain 15 byte
479 check_isotime (const gnupg_isotime_t atime
)
485 return gpg_error (GPG_ERR_NO_VALUE
);
487 for (s
=atime
, i
=0; i
< 8; i
++, s
++)
489 return gpg_error (GPG_ERR_INV_TIME
);
491 return gpg_error (GPG_ERR_INV_TIME
);
492 for (s
++, i
=9; i
< 15; i
++, s
++)
494 return gpg_error (GPG_ERR_INV_TIME
);
500 dump_isotime (const gnupg_isotime_t t
)
503 log_printf (_("[none]"));
505 log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s",
506 t
, t
+4, t
+6, t
+9, t
+11, t
+13);
510 /* Add SECONDS to ATIME. SECONDS may not be negative and is limited
511 to about the equivalent of 62 years which should be more then
512 enough for our purposes. */
514 add_seconds_to_isotime (gnupg_isotime_t atime
, int nseconds
)
517 int year
, month
, day
, hour
, minute
, sec
, ndays
;
520 err
= check_isotime (atime
);
524 if (nseconds
< 0 || nseconds
>= (0x7fffffff - 61) )
525 return gpg_error (GPG_ERR_INV_VALUE
);
527 year
= atoi_4 (atime
+0);
528 month
= atoi_2 (atime
+4);
529 day
= atoi_2 (atime
+6);
530 hour
= atoi_2 (atime
+9);
531 minute
= atoi_2 (atime
+11);
532 sec
= atoi_2 (atime
+13);
534 if (year
<= 1582) /* The julian date functions don't support this. */
535 return gpg_error (GPG_ERR_INV_VALUE
);
545 jd
= date2jd (year
, month
, day
) + ndays
;
546 jd2date (jd
, &year
, &month
, &day
);
548 if (year
> 9999 || month
> 12 || day
> 31
549 || year
< 0 || month
< 1 || day
< 1)
550 return gpg_error (GPG_ERR_INV_VALUE
);
552 snprintf (atime
, 16, "%04d%02d%02dT%02d%02d%02d",
553 year
, month
, day
, hour
, minute
, sec
);
559 add_days_to_isotime (gnupg_isotime_t atime
, int ndays
)
562 int year
, month
, day
, hour
, minute
, sec
;
565 err
= check_isotime (atime
);
569 if (ndays
< 0 || ndays
>= 9999*366 )
570 return gpg_error (GPG_ERR_INV_VALUE
);
572 year
= atoi_4 (atime
+0);
573 month
= atoi_2 (atime
+4);
574 day
= atoi_2 (atime
+6);
575 hour
= atoi_2 (atime
+9);
576 minute
= atoi_2 (atime
+11);
577 sec
= atoi_2 (atime
+13);
579 if (year
<= 1582) /* The julian date functions don't support this. */
580 return gpg_error (GPG_ERR_INV_VALUE
);
582 jd
= date2jd (year
, month
, day
) + ndays
;
583 jd2date (jd
, &year
, &month
, &day
);
585 if (year
> 9999 || month
> 12 || day
> 31
586 || year
< 0 || month
< 1 || day
< 1)
587 return gpg_error (GPG_ERR_INV_VALUE
);
589 snprintf (atime
, 16, "%04d%02d%02dT%02d%02d%02d",
590 year
, month
, day
, hour
, minute
, sec
);