Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into strtime

  • Loading branch information...
commit 790d633c8077aeba06ca687d41cd53bf00f20cbb 2 parents 17a5de9 + da5ae4e
@schwern authored
View
26 .gitignore
@@ -0,0 +1,26 @@
+*.bak
+*~
+*.old
+Makefile
+blib/
+pm_to_blib
+Build
+_build
+cover_db/
+nytprof*
+*.patch
+.DS_Store
+MYMETA.yml
+*.o
+t/*.out.bz2
+t/gmtime_test
+t/localtime_test
+t/asctime64.t
+t/ctime64.t
+t/gmtime64.t
+t/negative.t
+t/overflow.t
+t/safe_year.t
+t/safe_year.t.dSYM/
+t/timegm.t
+t/year_limit.t
View
18 INSTALL
@@ -1,7 +1,15 @@
+There is currently no installer, sorry. If somebody wants to take a
+crack at it, please go ahead.
+
This project is not intended to be installed on your system, but to be
-used as part of an application or project. Simply copy time64.c and
-time64.h into your project, compile them as part of your build process
-and include them instead of (or in addition to) time.h.
+used as part of an application or project. It is written to the POSIX
+time.h standard and should work with any ANSI C 89 compiler.
+
+This project consists of a few C and header files which should be copied
+and built like any other ANSI C code.
-It is written to the POSIX time.h standard and should work with any
-ANSI C 89 compiler.
+1) Copy time64.c, time64.h and time64_config.h into your C project.
+2) Tweak configuration values in time64_config.h.
+3) #include "time64.h" in your code and make use of the new functions
+ in place of time.h's.
+4) Build your C project normally.
View
35 README.txt
@@ -7,9 +7,22 @@ It makes use of the system's native 32 bit functions to perform time
zone and daylight savings time calculations and thus does *not* need
to ship its own time zone table.
-time64.h currently implements three public functions, localtime64_r(),
-gmtime64_r() and timegm64(). They are implementations of
-localtime_r(), gmtime_r() and timegm64().
+Here is a list of the currently implemented functions in time64.h and
+their POSIX time.h equivalents.
+
+ time64.h time.h
+ -------- ------
+ localtime64_r localtime_r
+ localtime64 localtime
+ gmtime64_r gmtime_r
+ gmtime64 gmtime
+ asctime64_r asctime_r
+ asctime64 asctime
+ ctime64_r ctime_r
+ ctime64 ctime
+ timelocal64 mktime
+ mktime64 mktime
+ timegm64 timegm (a GNU extension)
To install, simply copy time64.c and time64.h into your project and
make use of the functions.
@@ -24,19 +37,21 @@ different time zones.
Limitations, Issues, etc...
---------------------------
-localtime64_r() gets its time zone and daylight savings time information by
-mappping the future year back to a similar one between 2010 and 2037, safe
-for localtime_r(). The calculations are accurate according to current time
-zone and daylight savings information, but may become inaccurate if a
-change is made that takes place after 2010.
+localtime64_r() gets its time zone and daylight savings time
+information by mappping the future year back to a similar one between
+2010 and 2037, safe for localtime_r(). The calculations are accurate
+according to current time zone and daylight savings information, but
+may become inaccurate if a change is made that takes place after 2010.
+But its better to be off by an hour than 137 years.
Future versions will probe for a 64 bit safe system localtime_r() and
-gmtime_r() and use that.
+gmtime_r() and use that. You can manually set the safe range of your
+system in time64_config.h.
The maximum date is still limited by your tm struct. Most 32 bit
systems use a signed integer tm_year which means the practical upper
limit is the year 2147483647 which is somewhere around 2**54. You can
-use a 64 bit clean tm struct by setting USE_TM64 in time64.h
+use a 64 bit clean tm struct by setting USE_TM64 in time64_config.h
Portability
View
3  perl/Time-y2038/.gitignore
@@ -0,0 +1,3 @@
+check_max
+lib/Time/y2038.c
+y2038/time64_config.h
View
2  perl/Time-y2038/Build.PL
@@ -38,6 +38,8 @@ my $build = Local::Module::Build->new(
requires => {
perl => '5.6.1'
},
+
+ add_to_cleanup => [qw(check_max.o check_max)],
);
$build->create_build_script;
View
3  perl/Time-y2038/inc/Local/Module/Build.pm
@@ -18,7 +18,8 @@ sub note_time_limits {
$self->add_to_cleanup($exe);
}
- return if $self->up_to_date(["munge_config", $exe] => "y2038/time64_config.h");
+ return if $self->up_to_date(["y2038/time64_config.h.in", "munge_config", $exe]
+ => "y2038/time64_config.h");
warn " and running it...\n";
my @maxes = `./$exe`;
View
25 perl/Time-y2038/t/time.t
@@ -66,6 +66,31 @@ SKIP: {
}
+# Some sanity tests for the far, far future and far, far past
+{
+ my %time2year = (
+ -2**62 => -146138510344,
+ -2**52 => -142711421,
+ -2**48 => -8917617,
+ -2**46 => -2227927,
+ 2**46 => 2231866,
+ 2**48 => 8921556,
+ 2**52 => 142715360,
+ 2**62 => 146138514283
+ );
+
+ for my $time (sort keys %time2year) {
+ my $want = $time2year{$time};
+
+ my $have = (gmtime($time))[5] + 1900;
+ is $have, $want, "year check, gmtime($time)";
+
+ $have = (localtime($time))[5] + 1900;
+ is $have, $want, "year check, localtime($time)";
+ }
+}
+
+
for my $name (qw(gmtime localtime)) {
my $func = do {
no strict 'refs';
View
5 perl/Time-y2038/y2038/time64_config.h.in
@@ -27,6 +27,11 @@
with tm. Conversion functions will be provided.
*/
#define USE_TM64
+#ifdef USE_TM64
+ #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %lld\n"
+#else
+ #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n"
+#endif
/* Availability of system functions.
View
2  t/safe_year.t.c
@@ -34,7 +34,7 @@ static void year_to_tm(const Year year, struct tm *ret) {
time = timegm64(&date);
gmtime64_r(&time, &date);
- copy_TM_to_tm(&date, ret);
+ copy_TM64_to_tm(&date, ret);
}
View
56 time64.c
@@ -150,22 +150,22 @@ static const int dow_year_start[SOLAR_CYCLE_LENGTH] = {
/* Multi varadic macros are a C99 thing, alas */
#ifdef TIME_64_DEBUG
-# define TRACE(format) (fprintf(stderr, format))
-# define TRACE1(format, var1) (fprintf(stderr, format, var1))
-# define TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2))
-# define TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3))
+# define TIME64_TRACE(format) (fprintf(stderr, format))
+# define TIME64_TRACE1(format, var1) (fprintf(stderr, format, var1))
+# define TIME64_TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2))
+# define TIME64_TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3))
#else
-# define TRACE(format) ((void)0)
-# define TRACE1(format, var1) ((void)0)
-# define TRACE2(format, var1, var2) ((void)0)
-# define TRACE3(format, var1, var2, var3) ((void)0)
+# define TIME64_TRACE(format) ((void)0)
+# define TIME64_TRACE1(format, var1) ((void)0)
+# define TIME64_TRACE2(format, var1, var2) ((void)0)
+# define TIME64_TRACE3(format, var1, var2, var3) ((void)0)
#endif
static int is_exception_century(Year year)
{
int is_exception = ((year % 100 == 0) && !(year % 400 == 0));
- TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no");
+ TIME64_TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no");
return(is_exception);
}
@@ -192,7 +192,7 @@ Time64_T timegm64(const struct TM *date) {
orig_year -= cycles * 400;
days += (Time64_T)cycles * days_in_gregorian_cycle;
}
- TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year);
+ TIME64_TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year);
if( orig_year > 70 ) {
year = 70;
@@ -270,7 +270,7 @@ static Year cycle_offset(Year year)
exceptions = year_diff / 100;
exceptions -= year_diff / 400;
- TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n",
+ TIME64_TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n",
year, exceptions, year_diff);
return exceptions * 16;
@@ -329,7 +329,7 @@ static int safe_year(const Year year)
else
assert(0);
- TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n",
+ TIME64_TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n",
year, year_cycle, safe_year);
assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR);
@@ -338,7 +338,7 @@ static int safe_year(const Year year)
}
-void copy_tm_to_TM(const struct tm *src, struct TM *dest) {
+void copy_tm_to_TM64(const struct tm *src, struct TM *dest) {
if( src == NULL ) {
memset(dest, 0, sizeof(*dest));
}
@@ -370,7 +370,7 @@ void copy_tm_to_TM(const struct tm *src, struct TM *dest) {
}
-void copy_TM_to_tm(const struct TM *src, struct tm *dest) {
+void copy_TM64_to_tm(const struct TM *src, struct tm *dest) {
if( src == NULL ) {
memset(dest, 0, sizeof(*dest));
}
@@ -468,14 +468,14 @@ Time64_T mktime64(const struct TM *input_date) {
Year year = input_date->tm_year + 1900;
if( MIN_SAFE_YEAR <= year && year <= MAX_SAFE_YEAR ) {
- copy_TM_to_tm(input_date, &safe_date);
+ copy_TM64_to_tm(input_date, &safe_date);
return (Time64_T)mktime(&safe_date);
}
/* Have to make the year safe in date else it won't fit in safe_date */
date = *input_date;
date.tm_year = safe_year(year) - 1900;
- copy_TM_to_tm(&date, &safe_date);
+ copy_TM64_to_tm(&date, &safe_date);
time = (Time64_T)mktime(&safe_date);
@@ -505,11 +505,11 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p)
/* Use the system gmtime() if time_t is small enough */
if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) {
- time_t safe_time = *in_time;
+ time_t safe_time = (time_t)*in_time;
struct tm safe_date;
GMTIME_R(&safe_time, &safe_date);
- copy_tm_to_TM(&safe_date, p);
+ copy_tm_to_TM64(&safe_date, p);
assert(check_tm(p));
return p;
@@ -630,20 +630,20 @@ struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm)
/* Use the system localtime() if time_t is small enough */
if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) {
- safe_time = *time;
+ safe_time = (time_t)*time;
- TRACE1("Using system localtime for %lld\n", *time);
+ TIME64_TRACE1("Using system localtime for %lld\n", *time);
LOCALTIME_R(&safe_time, &safe_date);
- copy_tm_to_TM(&safe_date, local_tm);
+ copy_tm_to_TM64(&safe_date, local_tm);
assert(check_tm(local_tm));
return local_tm;
}
if( gmtime64_r(time, &gm_tm) == NULL ) {
- TRACE1("gmtime64_r returned null for %lld\n", *time);
+ TIME64_TRACE1("gmtime64_r returned null for %lld\n", *time);
return NULL;
}
@@ -653,21 +653,21 @@ struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm)
gm_tm.tm_year < (1970 - 1900)
)
{
- TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year);
+ TIME64_TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year);
gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900;
}
- safe_time = timegm64(&gm_tm);
+ safe_time = (time_t)timegm64(&gm_tm);
if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) {
- TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time);
+ TIME64_TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time);
return NULL;
}
- copy_tm_to_TM(&safe_date, local_tm);
+ copy_tm_to_TM64(&safe_date, local_tm);
local_tm->tm_year = orig_year;
if( local_tm->tm_year != orig_year ) {
- TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n",
+ TIME64_TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n",
(Year)local_tm->tm_year, (Year)orig_year);
#ifdef EOVERFLOW
@@ -729,7 +729,7 @@ char *asctime64_r( const struct TM* date, char *result ) {
if( !valid_tm_wday(date) || !valid_tm_mon(date) )
return NULL;
- sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ sprintf(result, TM64_ASCTIME_FORMAT,
wday_name[date->tm_wday],
mon_name[date->tm_mon],
date->tm_mday, date->tm_hour,
View
6 time64_config.h
@@ -27,7 +27,11 @@
with tm. Conversion functions will be provided.
*/
/* #define USE_TM64 */
-
+#ifdef USE_TM64
+ #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %lld\n"
+#else
+ #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n"
+#endif
/* HAVE_STDINT */
#define HAVE_STDINT
Please sign in to comment.
Something went wrong with that request. Please try again.