Thursday, June 13, 2013

Year 2038 problem in 32 bit machine

The unix time stamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970. Therefore, the unix time stamp is merely the number of seconds between a particular date and the Unix Epoch.

On January 19, 2038 the Unix Time Stamp will cease to work due to a 32-bit overflow. The last timestamp that is working in 32 bit is 19.01.2038 03:14:07 ( =2147480047 ) After this second, timestamp number crosses 32 bit signed integer range.

Before this moment millions of applications will need to either adopt a new convention for time stamps or be migrated to 64-bit systems which will buy the time stamp a "bit" more time.

In PHP most important date functions are:
date and strtotime
We will use both functions in simple calendar application.


date: Returns a string formatted according to the given format string using the given integer timestamp or the current time if no timestamp is given.
Syntax: string date ( string $format [, int $timestamp = time() ] )


strtotime: Parse about any English textual datetime description into a Unix timestamp
Syntax: int strtotime ( string $time [, int $now = time() ] )

We should relay on unix timestamp in above two functions.

As per 32 bit Signed integer storage capacity, the unix timestamp will not parse by date function after the above mentioned date.

So, we need an alternate for this issue:


In astronomical calculations, we use Julian Day for day-number calendar. The Julian Day Number (JDN) is the integer assigned to a whole solar day in the Julian day count starting from noon Greenwich Mean Time, with Julian day number 0 assigned to the day starting at noon on January 1, 4713 BC

The Julian Date of any instant is the Julian day number for the preceding noon plus the fraction of the day since that instant. Julian Dates are expressed as a Julian day number with a decimal fraction added. The Julian Date for 22:44, 17 May 2013 (UTC) is 2456430.4476852.


Solution:

For the dates after January 19, 2038 we can make use of this Julian day-number and we can convert this Julian day number to Western/Gregorian calendar month day and year format.

For that we have two built in PHP functions:
gregoriantojd and JDToGregorian

These two functions are not relying on Unix TimeStamp. A simple arithmetic operations can do these conversions.


Below are the user defined functions which can give the idea on this date conversion algorithm.


// calculate Julian Day from Month, Day and Year
function mdy2julian($m,$d,$y)
{
$im = 12 * ($y + 4800) + $m - 3;
$j = (2 * ($im - floor($im/12) * 12) + 7 + 365 * $im)/12;
$j = floor($j) + $d + floor($im/48) - 32083;
if($j > 2299171) $j += floor($im/4800) - floor($im/1200) + 38;
return $j;
}


//calculate gregorian day to the julian day-number
function jd_to_greg($julian) {
$julian = $julian - 1721119;
$calc1 = 4 * $julian - 1;
$year = floor($calc1 / 146097);
$julian = floor($calc1 - 146097 * $year);
$day = floor($julian / 4);
$calc2 = 4 * $day + 3;
$julian = floor($calc2 / 1461);
$day = $calc2 - 1461 * $julian;
$day = floor(($day + 4) / 4);
$calc3 = 5 * $day - 3;
$month = floor($calc3 / 153);
$day = $calc3 - 153 * $month;
$day = floor(($day + 5) / 5);
$year = 100 * $year + $julian;

if ($month < 10) {
$month = $month + 3;
}
else {
$month = $month - 9;
$year = $year + 1;
}
return "$day/$month/$year";
}


References:
https://bugs.php.net/bug.php?id=7103
http://en.wikipedia.org/wiki/Year_2038_problem
http://en.wikipedia.org/wiki/Julian_day
http://php.net/manual/en/function.gregoriantojd.php
http://www.php.net/manual/en/function.jdtogregorian.php

No comments:

Post a Comment