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
30 static unsigned long timewarp
;
31 static enum { NORMAL
= 0, FROZEN
, FUTURE
, PAST
} timemode
;
33 /* Correction used to map to real Julian days. */
34 #define JD_DIFF 1721060L
37 /* Wrapper for the time(3). We use this here so we can fake the time
42 time_t current
= time (NULL
);
43 if (timemode
== NORMAL
)
45 else if (timemode
== FROZEN
)
47 else if (timemode
== FUTURE
)
48 return current
+ timewarp
;
50 return current
- timewarp
;
54 /* Return the current time (possibly faked) in ISO format. */
56 gnupg_get_isotime (gnupg_isotime_t timebuf
)
58 time_t atime
= gnupg_get_time ();
68 tp
= gmtime_r (&atime
, &tmbuf
);
72 snprintf (timebuf
, 16, "%04d%02d%02dT%02d%02d%02d",
73 1900 + tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
74 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
79 /* Set the time to NEWTIME so that gnupg_get_time returns a time
80 starting with this one. With FREEZE set to 1 the returned time
81 will never change. Just for completeness, a value of (time_t)-1
82 for NEWTIME gets you back to reality. Note that this is obviously
83 not thread-safe but this is not required. */
85 gnupg_set_time (time_t newtime
, int freeze
)
87 time_t current
= time (NULL
);
89 if ( newtime
== (time_t)-1 || current
== newtime
)
99 else if (newtime
> current
)
102 timewarp
= newtime
- current
;
107 timewarp
= current
- newtime
;
111 /* Returns true when we are in timewarp mode */
113 gnupg_faked_time_p (void)
119 /* This function is used by gpg because OpenPGP defines the timestamp
120 as an unsigned 32 bit value. */
122 make_timestamp (void)
124 time_t t
= gnupg_get_time ();
127 log_fatal ("gnupg_get_time() failed\n");
134 * Scan a date string and return a timestamp.
135 * The only supported format is "yyyy-mm-dd"
136 * Returns 0 for an invalid date.
139 scan_isodatestr( const char *string
)
141 int year
, month
, day
;
146 if( strlen(string
) != 10 || string
[4] != '-' || string
[7] != '-' )
148 for( i
=0; i
< 4; i
++ )
149 if( !digitp (string
+i
) )
151 if( !digitp (string
+5) || !digitp(string
+6) )
153 if( !digitp(string
+8) || !digitp(string
+9) )
156 month
= atoi(string
+5);
157 day
= atoi(string
+8);
158 /* some basic checks */
159 if( year
< 1970 || month
< 1 || month
> 12 || day
< 1 || day
> 31 )
161 memset( &tmbuf
, 0, sizeof tmbuf
);
163 tmbuf
.tm_mon
= month
-1;
164 tmbuf
.tm_year
= year
- 1900;
166 stamp
= mktime( &tmbuf
);
167 if( stamp
== (time_t)-1 )
172 /* Scan am ISO timestamp and return an Epoch based timestamp. The only
173 supported format is "yyyymmddThhmmss" delimited by white space, nul, a
174 colon or a comma. Returns (time_t)(-1) for an invalid string. */
176 isotime2epoch (const char *string
)
179 int year
, month
, day
, hour
, minu
, sec
;
185 for (s
=string
, i
=0; i
< 8; i
++, s
++)
190 for (s
++, i
=9; i
< 15; i
++, s
++)
193 if ( !(!*s
|| (isascii (*s
) && isspace(*s
)) || *s
== ':' || *s
== ','))
194 return (time_t)(-1); /* Wrong delimiter. */
196 year
= atoi_4 (string
);
197 month
= atoi_2 (string
+ 4);
198 day
= atoi_2 (string
+ 6);
199 hour
= atoi_2 (string
+ 9);
200 minu
= atoi_2 (string
+ 11);
201 sec
= atoi_2 (string
+ 13);
204 if (year
< 1970 || month
< 1 || month
> 12 || day
< 1 || day
> 31
205 || hour
> 23 || minu
> 59 || sec
> 61 )
208 memset (&tmbuf
, 0, sizeof tmbuf
);
211 tmbuf
.tm_hour
= hour
;
213 tmbuf
.tm_mon
= month
-1;
214 tmbuf
.tm_year
= year
- 1900;
216 return timegm (&tmbuf
);
220 /* Convert an Epoch time to an iso time stamp. */
222 epoch2isotime (gnupg_isotime_t timebuf
, time_t atime
)
232 tp
= gmtime_r (&atime
, &tmbuf
);
234 tp
= gmtime (&atime
);
236 snprintf (timebuf
, 16, "%04d%02d%02dT%02d%02d%02d",
237 1900 + tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
238 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
246 add_days_to_timestamp( u32 stamp
, u16 days
)
248 return stamp
+ days
*86400L;
253 * Return a string with a time value in the form: x Y, n D, n H
257 strtimevalue( u32 value
)
259 static char buffer
[30];
260 unsigned int years
, days
, hours
, minutes
;
263 minutes
= value
% 60;
271 sprintf(buffer
,"%uy%ud%uh%um", years
, days
, hours
, minutes
);
275 return strchr( buffer
, 'y' ) + 1;
276 return strchr( buffer
, 'd' ) + 1;
281 * Note: this function returns GMT
284 strtimestamp( u32 stamp
)
286 static char buffer
[11+5];
288 time_t atime
= stamp
;
291 strcpy (buffer
, "????" "-??" "-??");
294 tp
= gmtime( &atime
);
295 sprintf(buffer
,"%04d-%02d-%02d",
296 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
);
303 * Note: this function returns GMT
306 isotimestamp (u32 stamp
)
308 static char buffer
[25+5];
310 time_t atime
= stamp
;
314 strcpy (buffer
, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
318 tp
= gmtime ( &atime
);
319 sprintf (buffer
,"%04d-%02d-%02d %02d:%02d:%02d",
320 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
321 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
328 * Note: this function returns local time
331 asctimestamp( u32 stamp
)
333 static char buffer
[50];
334 #if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
338 time_t atime
= stamp
;
341 strcpy (buffer
, "????" "-??" "-??");
345 tp
= localtime( &atime
);
347 #if defined(HAVE_NL_LANGINFO)
348 mem2str( fmt
, nl_langinfo(D_T_FMT
), DIM(fmt
)-3 );
349 if( strstr( fmt
, "%Z" ) == NULL
)
351 /* NOTE: gcc -Wformat-noliteral will complain here. I have
352 found no way to suppress this warning .*/
353 strftime (buffer
, DIM(buffer
)-1, fmt
, tp
);
355 /* FIXME: we should check whether the locale appends a " %Z"
356 * These locales from glibc don't put the " %Z":
357 * fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
359 strftime( buffer
, DIM(buffer
)-1, "%c %Z", tp
);
361 buffer
[DIM(buffer
)-1] = 0;
363 mem2str( buffer
, asctime(tp
), DIM(buffer
) );
371 days_per_year (int y
)
379 return s
? 366 : 365;
383 days_per_month (int y
, int m
)
389 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
397 case 4: case 6: case 9: case 11:
404 /* Convert YEAR, MONTH and DAY into the Julian date. We assume that
405 it is already noon. We do not support dates before 1582-10-15. */
407 date2jd (int year
, int month
, int day
)
411 jd
= 365L * year
+ 31 * (month
-1) + day
+ JD_DIFF
;
415 jd
-= (4 * month
+ 23) / 10;
417 jd
+= year
/ 4 - ((year
/ 100 + 1) *3) / 4;
422 /* Convert a Julian date back to YEAR, MONTH and DAY. Return day of
423 the year or 0 on error. This function uses some more or less
424 arbitrary limits, most important is that days before 1582 are not
427 jd2date (unsigned long jd
, int *year
, int *month
, int *day
)
434 if (jd
< 1721425 || jd
> 2843085)
437 y
= (jd
- JD_DIFF
) / 366;
440 while ((delta
= jd
- date2jd (y
, m
, d
)) > days_per_year (y
))
443 m
= (delta
/ 31) + 1;
444 while( (delta
= jd
- date2jd (y
, m
, d
)) > days_per_month (y
,m
))
452 if (d
> days_per_month (y
, m
))
470 return (jd
- date2jd (y
, 1, 1)) + 1;
474 /* Check that the 15 bytes in ATIME represent a valid ISO time. Note
475 that this function does not expect a string but a plain 15 byte
478 check_isotime (const gnupg_isotime_t atime
)
484 return gpg_error (GPG_ERR_NO_VALUE
);
486 for (s
=atime
, i
=0; i
< 8; i
++, s
++)
488 return gpg_error (GPG_ERR_INV_TIME
);
490 return gpg_error (GPG_ERR_INV_TIME
);
491 for (s
++, i
=9; i
< 15; i
++, s
++)
493 return gpg_error (GPG_ERR_INV_TIME
);
499 /* Add SECONDS to ATIME. SECONDS may not be negative and is limited
500 to about the equivalent of 62 years which should be more then
501 enough for our purposes. */
503 add_seconds_to_isotime (gnupg_isotime_t atime
, int nseconds
)
506 int year
, month
, day
, hour
, minute
, sec
, ndays
;
509 err
= check_isotime (atime
);
513 if (nseconds
< 0 || nseconds
>= (0x7fffffff - 61) )
514 return gpg_error (GPG_ERR_INV_VALUE
);
516 year
= atoi_4 (atime
+0);
517 month
= atoi_2 (atime
+4);
518 day
= atoi_2 (atime
+6);
519 hour
= atoi_2 (atime
+9);
520 minute
= atoi_2 (atime
+11);
521 sec
= atoi_2 (atime
+13);
523 if (year
<= 1582) /* The julian date functions don't support this. */
524 return gpg_error (GPG_ERR_INV_VALUE
);
534 jd
= date2jd (year
, month
, day
) + ndays
;
535 jd2date (jd
, &year
, &month
, &day
);
537 if (year
> 9999 || month
> 12 || day
> 31
538 || year
< 0 || month
< 1 || day
< 1)
539 return gpg_error (GPG_ERR_INV_VALUE
);
541 snprintf (atime
, 16, "%04d%02d%02dT%02d%02d%02d",
542 year
, month
, day
, hour
, minute
, sec
);
548 add_days_to_isotime (gnupg_isotime_t atime
, int ndays
)
551 int year
, month
, day
, hour
, minute
, sec
;
554 err
= check_isotime (atime
);
558 if (ndays
< 0 || ndays
>= 9999*366 )
559 return gpg_error (GPG_ERR_INV_VALUE
);
561 year
= atoi_4 (atime
+0);
562 month
= atoi_2 (atime
+4);
563 day
= atoi_2 (atime
+6);
564 hour
= atoi_2 (atime
+9);
565 minute
= atoi_2 (atime
+11);
566 sec
= atoi_2 (atime
+13);
568 if (year
<= 1582) /* The julian date functions don't support this. */
569 return gpg_error (GPG_ERR_INV_VALUE
);
571 jd
= date2jd (year
, month
, day
) + ndays
;
572 jd2date (jd
, &year
, &month
, &day
);
574 if (year
> 9999 || month
> 12 || day
> 31
575 || year
< 0 || month
< 1 || day
< 1)
576 return gpg_error (GPG_ERR_INV_VALUE
);
578 snprintf (atime
, 16, "%04d%02d%02dT%02d%02d%02d",
579 year
, month
, day
, hour
, minute
, sec
);