select unix_timestamp('2038-01-19') returns 2147472000
while select unix_timestamp('2038-01-20') returns 0
I have checked out the year 2038 problem.
My linux OS is 64 bit and installed mysql version is also 64 bits. What is the solution to this problem now?
mysql --version returns mysql Ver 14.14 Distrib 5.5.47, for Linux (x86_64) using readline 5.1
Php is 64 bit too.
Tried BigInt too, didn't work (returns the same thing).
Simply put, for MySQL, store dates as DATETIME rather than TIMESTAMP.
TIMESTAMP is 4 bytes, so there is no physical room to store more seconds than since 1970-1-1 to 2038-01-19...
DATETIME, instead, has a range of 1000-1-1 to 9999-12-31...
See also this complete question/answer: PHP & mySQL: Year 2038 Bug: What is it? How to solve it?
UPDATE:
One possible alternative I see, if you CAN'T change your fields types, is to interpet your timestamps differently...
I mean: if the first event your application will keep track of is - say - 2000-1-1, you could implement a filter on backend (or in a stored procedure inside the database), to add (2000-1-1 - 1970-1-1) seconds to your timestamps when reading, and subtract the same amount when reading... This should give you 30 more years of 'survival'...
MySQL documentation is in general extremely vague about the data types returned by functions and UNIX_TIMESTAMP() is not an exception. Unless we check the source code I think we can only make an educated guess.
At Date and Time Type Overview we can read that the TIMESTAMP data type itself has a documented range that doesn't depend on the server architecture:
The range is '1970-01-01 00:00:01.000000' UTC to
'2038-01-19 03:14:07.999999' UTC. TIMESTAMP values are stored as the
number of seconds since the epoch ('1970-01-01 00:00:00' UTC). A
TIMESTAMP cannot represent the value '1970-01-01 00:00:00' because
that is equivalent to 0 seconds from the epoch and the value 0 is
reserved for representing '0000-00-00 00:00:00', the “zero” TIMESTAMP
value.
Even if we make sure we pass a proper date type:
mysql> select
-> str_to_date('2038-01-20', '%Y-%m-%d'),
-> unix_timestamp(str_to_date('2038-01-20', '%Y-%m-%d'));
+---------------------------------------+-------------------------------------------------------+
| str_to_date('2038-01-20', '%Y-%m-%d') | unix_timestamp(str_to_date('2038-01-20', '%Y-%m-%d')) |
+---------------------------------------+-------------------------------------------------------+
| 2038-01-20 | 0 |
+---------------------------------------+-------------------------------------------------------+
1 row in set (0.01 sec)
... we still get 0, the silly function flag for errors:
If you pass an out-of-range date to UNIX_TIMESTAMP(), it returns 0.
So it's kind of safe to assume that UNIX_TIMESTAMP() returns a value of TIMESTAMP type thus 2038+ is not supported.
In short: you'll have to calculate timestamps somewhere else (i.e., your client code). Since there's a PHP tag:
$t = new DateTime('2038-01-20', new DateTimeZone('UTC'));
var_dump( $t->format('U') );
string(10) "2147558400"
P.S. MariaDB, the MySQL fork, has the same restriction but it documents it better:
Timestamps in MariaDB have a maximum value of 2147483647, equivalent
to 2038-01-19 05:14:07. This is due to the underlying 32-bit
limitation. Using the function on a date beyond this will result in
NULL being returned.
Related
I was thinking of using TIMESTAMP to store the date+time, but I read that there is a limitation of year 2038 on it. Instead of asking my question in bulk, I preferred to break it up into small parts so that it is easy for novice users to understand as well. So my question(s):
What exactly is the Year 2038 problem?
Why does it occur and what happens when it occurs?
How do we solve it?
Are there any possible alternatives to using it, which do not pose a similar problem?
What can we do to the existing applications that use TIMESTAMP, to avoid the so-called problem, when it really occurs?
I have marked this as a community wiki so feel free to edit at your leisure.
What exactly is the Year 2038 problem?
"The year 2038 problem (also known as Unix Millennium Bug, Y2K38 by analogy to the Y2K problem) may cause some computer software to fail before or in the year 2038. The problem affects all software and systems that store system time as a signed 32-bit integer, and interpret this number as the number of seconds since 00:00:00 UTC on January 1, 1970."
Why does it occur and what happens when it occurs?
Times beyond 03:14:07 UTC on Tuesday, 19 January 2038 will 'wrap around' and be stored internally as a negative number, which these systems will interpret as a time in December 13, 1901 rather than in 2038. This is due to the fact that the number of seconds since the UNIX epoch (January 1 1970 00:00:00 GMT) will have exceeded a computer's maximum value for a 32-bit signed integer.
How do we solve it?
Use long data types (64 bits is sufficient)
For MySQL (or MariaDB), if you don't need the time information consider using the DATE column type. If you need higher accuracy, use DATETIME rather than TIMESTAMP. Beware that DATETIME columns do not store information about the timezone, so your application will have to know which timezone was used.
Other Possible solutions described on Wikipedia
Upgrade your Mysql to 8.0.28 or higher
Are there any possible alternatives to using it, which do not pose a similar problem?
Try wherever possible to use large types for storing dates in databases: 64-bits is sufficient - a long long type in GNU C and POSIX/SuS, or sprintf('%u'...) in PHP or the BCmath extension.
What are some potentially breaking use cases even though we're not yet in 2038?
So a MySQL DATETIME has a range of 1000-9999, but TIMESTAMP only has a range of 1970-2038. If your system stores birthdates, future forward dates (e.g. 30 year mortgages), or similar, you're already going to run into this bug. Again, don't use TIMESTAMP if this is going to be a problem.
What can we do to the existing applications that use TIMESTAMP, to avoid the so-called problem, when it really occurs?
Few PHP applications will still be around in 2038, though it's hard to foresee as the web hardly a legacy platform yet.
Here is a process for altering a database table column to convert TIMESTAMP to DATETIME. It starts with creating a temporary column:
# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;
# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;
# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);
# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`
Resources
Year 2038 Problem (Wikipedia)
The Internet Will End in 30 Years
When using UNIX Timestamps to store dates, you are actually using a 32 bits integers, that keeps count of the number of seconds since 1970-01-01 ; see Unix Time
That 32 bits number will overflow in 2038. That's the 2038 problem.
To solve that problem, you must not use a 32 bits UNIX timestamp to store your dates -- which means, when using MySQL, you should not use TIMESTAMP, but DATETIME (see 10.3.1. The DATETIME, DATE, and TIMESTAMP Types) :
The DATETIME type is used when you
need values that contain both date and
time information. The supported range
is '1000-01-01 00:00:00' to
'9999-12-31 23:59:59'.
The TIMESTAMP data type has a range
of '1970-01-01 00:00:01' UTC to
'2038-01-19 03:14:07' UTC.
The (probably) best thing you can do to your application to avoid/fix that problem is to not use TIMESTAMP, but DATETIME for the columns that have to contain dates that are not between 1970 and 2038.
One small note, though : there is a very high probably (statistically speaking) that your application will have been re-written quite a couple of times before 2038 ^^ So maybe, if you don't have to deal with dates in the future, you won't have to take care of that problem with the current version of your application...
A quick search on Google will do the trick: Year 2038 problem
The year 2038 problem (also known as Unix Millennium Bug, Y2K38 by analogy to the Y2K problem) may cause some computer software to fail before or in the year 2038
The problem affects all software and systems that store system time as a signed 32-bit integer, and interpret this number as the number of seconds since 00:00:00 UTC on January 1, 1970. The latest time that can be represented this way is 03:14:07 UTC on Tuesday, 19 January 2038. Times beyond this moment will "wrap around" and be stored internally as a negative number, which these systems will interpret as a date in 1901 rather than 2038
There is no easy fix for this problem for existing CPU/OS combinations, existing file systems, or existing binary data formats
http://en.wikipedia.org/wiki/Year_2038_problem has most of the details
In summary:
1) + 2) The problem is that many systems store date info as a 32-bit signed int equal to the number of seconds since 1/1/1970. The latest date that can be stored like this is 03:14:07 UTC on Tuesday, 19 January 2038. When this happens the int will "wrap around" and be stored as a negative number which will be interpreted as a date in 1901. What exactly will happen then, varies from system to system but suffice to say it probably won't be good for any of them!
For systems that only store dates in the past, then I guess you don't need to worry for a while! The main problem is with systems that work with dates in the future. If your system needs to work with dates 28 years in the future then you should start worrying now!
3) Use one of the alternative date formats available or move to a 64-bit system and use 64-bit ints. Or for databases use an alternative time stamp format (eg for MySQL use DATETIME)
4) See 3!
5) See 4!!! ;)
Bros, if you need to use PHP to display timestamps, this is the BEST PHP solution without changing from UNIX_TIMESTAMP format.
Use a custom_date() function. Inside it, use the DateTime. Here's the DateTime solution.
As long as you have UNSIGNED BIGINT(8) as your timestamps in database.
As long as you have PHP 5.2.0 ++
I was asking myself thses questions recently and want to share the solution I landed on for new projects.
Bigint
After reading variouse responses to questions like this one I found that storing a Unix timestamp in a Bigint column is a much better solution moving forward.
Bigints range will cover you from before the begining of time till the year 292277026596 wich may as well be called forever.
Pluss:
It uses the same 8bytes of storage that DATETIME uses.
Its timezone agnostic.
You can still use auto generated timestamps via DEFAULT (unix_timestamp())
range is so massive your server will turn into dust before wraparounds can happen, even if storing time in miliseconds.
DECIMAL
This is the solution I landed on as you get a bit more controll.
You can store an overkill date range like bigint or reduce it to something realistic and use less storage.
In my case I also want to store frations of a second as actual fractions, and I still wanted the timestamps gerated on insert.
Heres the column definition from my create table schema:
`created` decimal(18,2) NOT NULL DEFAULT (unix_timestamp(now(2))) COMMENT 'unix timestamp'
Using decimal(18,2) provides an absolutly overkill time range with the same storage as bigint/datetime while showing fractions of a second down to 2 digits.
Storage is based on the number of digits, 9 digits = 4bytes signed or unsigned it doesnt matter.
You could limit the range to something more realistic and use significantly less than datetime or increase the precision to nanoseconds. You decide whats important.
Another advantage is, if in the distant future you hit the limit of your range, Mysql will just tell you.
No wrap around issue will happen, instead you will get an error preventing the insertion and can easily alter the table again to add another digit.
This makes for a perfect sense to me I highly recommend starting new databases with this appraoch.
As I did't want to upgrade anything, I asked my backend (MSSQL) to do this job instead of PHP!
$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);
echo $row_tmp['next_date'];
May not be an efficient way, but it works.
I have been trying to convert Date of birth from my DB into DATE FORMat but i am facing the problem of there are some negative values in DOB fields which when i check from online FROM_UNIXTIME calclator then it give different result and if i check it with FROM_UNIXTIME(-957632400) then it always returns NULL for negative values . KIndly let me know how can i get date format from such UNIX format like from -957632400
We can do this instead:
FROM_UNIXTIME(0) + INTERVAL -957632400 SECOND
The FROM_UNIXTIME function is limited by the allowable range for the TIMESTAMP datatype, which is the standard 32-bit unsigned int range 1970-01-01 thru 2038-01-something. Other software has been updated to support 64-bit signed integers, but MySQL doesn't yet provide that functionality (at least not in 5.1.x).
The workaround in MySQL is avoid using the TIMESTAMP datatype and using the DATETIME datatype instead, when we need a larger range (e.g. dates before Jan 1, 1970).
We can use the DATE_ADD function to subtract seconds from Jan 1, 1970, like this:
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
N.B. You will probably need to account for timezone "offsets" from UTC in doing those types of calculations. MySQL is going to interpret DATETIME values as being specified in the time_zone setting of the current MySQL session, rather than UTC (time_zone = '+00:00')
FOLLOWUP:
Q: Okay, Means if we select dates below '1970-01-01 00:00:00' then the negative value saves in the db else it would be positive. Right? – soft genic
A: Uhhh, no. If you select date/datetime values before Jan 1, 1970, MySQL will return DATE or DATETIME values before Jan 1, 1970. If you store DATE or DATETIME values before Jan 1, 1970, then MySQL will store DATE or DATETIME value before Jan 1, 1970, within the allowable range supported by those datatypes. (something like 0001-01-01 thru 9999 ?)
If you need to store really really big positive and negative integers in the database, you would likely store those in a column defined as BIGINT.
The internal representation of a DATE column requires 3-bytes of storage, and DATETIME requires 8-bytes of storage (up to MySQL version 5.6.4. The internal representation and storage of DATE and DATETIME values changed in 5.6.4)
So no, MySQL does not store date values before 1970 as "negative integers".
If you think about it a bit, MySQL is free to implement whatever storage mechanism they want. (And each storage engine is free to serialize that representation to disk however it wants.)
Why 3 bytes for a date?
One option MySQL has (and I'm not representing that this is the way it is done) could be to break up the date into it's year month and day components.
The representation of integer values in the range - requires -
0 - 9999 - 14 bits
0 - 12 - 4 bits
0 - 31 - 5 bits
That's a total of 23 bits, which happens to handily fits into 3 bytes. This just demonstrates that it's not necessary for MySQL to represent date values before Jan 1. 1970 as negative integers, so we shouldn't make the assumption that it does. (But we'd really only be concerned with this level of detail if we were working on a storage engine for MySQL.)
From DATETIME to unix timestamp:
SELECT TIMESTAMPDIFF(SECOND, FROM_UNIXTIME(0), '1956-12-24 01:06:49');
From timestamp to DATETIME:
SELECT DATE_ADD(convert_tz(FROM_UNIXTIME(0), ##session.time_zone,'+00:00'), INTERVAL -410914391 SECOND);
I have to work with a postgres database 9.4 and i want to work with timestamp.
The first 'problem' is that when i create a timestamp column on postgres, i don't know what it does internally but when i query it returns '2010-10-30 00:00:00'
For me a timestamp is something like this 12569537329 (unix timestamp).
I say that because is a integer or a float, it's way easier for computer to deal comparing to string, and each country has his own time format, with unix timestamp is a number and end of story.
Querying from php the result is a string, so i have to make a bunch juggling and because of time zone, day light saving and other things something might could gone wrong.
I searched a lot of and can't find a way to work with unix timestamp on postgresql.
Can someone explain if there a way, or the right way to work and get as close as possible to unix timestamp.
UPDATE
One thing that i found that it gonna help me and it take a long time to discover that is possible on postgresql is change the Interval Output.
pg manual
In php the date interval for month is 'month' for pg is 'mon' on php it will understand mon as monday.
I think that if you have to juggle too much you are doing it wrong.
Gladly postgres let us to change that behavior for session or permanently.
So setting intervalstyle to iso_8601 it will work as php iso_8601 and will output P1M
Just convert the unix time_t to/from a timestamp, and use that in postgres:
CREATE TABLE omg
( seq SERIAL NOT NULL PRIMARY KEY
, stampthing TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO omg(stampthing) SELECT now();
INSERT INTO omg(stampthing) VALUES
('epoch'::timestamptz )
, ('epoch'::timestamptz + 12569537329 * '1 second'::interval)
;
SELECT stampthing
, DATE_PART('epoch',stampthing) AS original
FROM omg;
Output:
CREATE TABLE
INSERT 0 1
INSERT 0 2
stampthing | original
-------------------------------+------------------
2016-01-20 16:08:12.646172+01 | 1453302492.64617
1970-01-01 01:00:00+01 | 0
2368-04-24 20:08:49+02 | 12569537329
(3 rows)
If you just query a timestamp column in postgres, you'll get a formatted date. If you prefer the unix timestamp integer you can either cast it when you return it using a syntax like
select extract(epoch from '2011-11-15 00:00:00+01'::timestamp with time zone)::integer;
If you do this a lot, you may make a view with the extract.
or you can define your timestamp column as an integer and store your data using the extract()
I don't want to start another discussion of pro or contra between using DATETIME vs TIMESTAMP vs INT. (I've already read articles like Using MySQL's TIMESTAMP vs storing timestamps directly.)
I sometimes use INT data type to store unix timestamps in database. That's because date and time calculations in my applications where done with unix timestamps often (e.g. for session timeouts and token expiration). Furthermore data selection in database is faster than using DATETIME when I can compare integer values in WHERE clause simply. There are few tables with 10+ million rows (up to 100 million) where this 4 bytes really save storage (on disk and in memory because of smaller indexes) also.
Regarding Y2K38 problem, I assume (and hope so), that UNIX_TIMESTAMP in MySQL an time() in PHP will return 64bit values in future, so there will be no need to change something in the applications itself. The point is, I've stored all these pseudo integer timestamp in MySQL as unsigned integers (I mean INT not BIGINT). Sure, unsigned integer timestamps will overflow in year 2106, but that's a bit more time than 2038.
My question is now: assuming that UNIX_TIMESTAMP itself will work after 2038, could there be any problems in MySQL and/or PHP until 2106 when these timestamps are stored as unsigned integer in MySQL? (Please don't argue with: there will be a lot time to fix that until 2038, I want to clarify this from the point of the application are not touched any longer)
EDIT: Because the question came up: I store only current timestamps in these columns, no birthdates, no future dates. Only current timestamps, so I want to clarify if this would work after 2038.
Your assumption surrounding UNIX_TIMESTAMP() is a big one.
Currently, UNIX_TIMESTAMP returns 0 if you try
mysql> select unix_timestamp("2038-01-19" );
+-------------------------------+
| unix_timestamp("2038-01-19" ) |
+-------------------------------+
| 2147468400 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select unix_timestamp("2038-01-20");
+------------------------------+
| unix_timestamp("2038-01-20") |
+------------------------------+
| 0 |
+------------------------------+
1 row in set (0.00 sec)
While the storage of INTs longer than 32-bits will work, unless you know something about how the implementation of unix_timestamp(int64) will work, then the question is really more guesswork than facts.
This implies that any integer arithmetic you do will still be valid with 64-bit ints, so for finding expired sessions (timestamp + timeout < (seconds since 1970 in 64-bits)) will still work. Whether or not you can rely on from_unixtime() and unix_timestamp()-functions depend whether the solution is just to up the ante to 64-bits or if the whole world in the next 20-odd years decide to set a new epoch.
Nobody knows for sure.
I was thinking of using TIMESTAMP to store the date+time, but I read that there is a limitation of year 2038 on it. Instead of asking my question in bulk, I preferred to break it up into small parts so that it is easy for novice users to understand as well. So my question(s):
What exactly is the Year 2038 problem?
Why does it occur and what happens when it occurs?
How do we solve it?
Are there any possible alternatives to using it, which do not pose a similar problem?
What can we do to the existing applications that use TIMESTAMP, to avoid the so-called problem, when it really occurs?
I have marked this as a community wiki so feel free to edit at your leisure.
What exactly is the Year 2038 problem?
"The year 2038 problem (also known as Unix Millennium Bug, Y2K38 by analogy to the Y2K problem) may cause some computer software to fail before or in the year 2038. The problem affects all software and systems that store system time as a signed 32-bit integer, and interpret this number as the number of seconds since 00:00:00 UTC on January 1, 1970."
Why does it occur and what happens when it occurs?
Times beyond 03:14:07 UTC on Tuesday, 19 January 2038 will 'wrap around' and be stored internally as a negative number, which these systems will interpret as a time in December 13, 1901 rather than in 2038. This is due to the fact that the number of seconds since the UNIX epoch (January 1 1970 00:00:00 GMT) will have exceeded a computer's maximum value for a 32-bit signed integer.
How do we solve it?
Use long data types (64 bits is sufficient)
For MySQL (or MariaDB), if you don't need the time information consider using the DATE column type. If you need higher accuracy, use DATETIME rather than TIMESTAMP. Beware that DATETIME columns do not store information about the timezone, so your application will have to know which timezone was used.
Other Possible solutions described on Wikipedia
Upgrade your Mysql to 8.0.28 or higher
Are there any possible alternatives to using it, which do not pose a similar problem?
Try wherever possible to use large types for storing dates in databases: 64-bits is sufficient - a long long type in GNU C and POSIX/SuS, or sprintf('%u'...) in PHP or the BCmath extension.
What are some potentially breaking use cases even though we're not yet in 2038?
So a MySQL DATETIME has a range of 1000-9999, but TIMESTAMP only has a range of 1970-2038. If your system stores birthdates, future forward dates (e.g. 30 year mortgages), or similar, you're already going to run into this bug. Again, don't use TIMESTAMP if this is going to be a problem.
What can we do to the existing applications that use TIMESTAMP, to avoid the so-called problem, when it really occurs?
Few PHP applications will still be around in 2038, though it's hard to foresee as the web hardly a legacy platform yet.
Here is a process for altering a database table column to convert TIMESTAMP to DATETIME. It starts with creating a temporary column:
# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;
# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;
# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);
# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`
Resources
Year 2038 Problem (Wikipedia)
The Internet Will End in 30 Years
When using UNIX Timestamps to store dates, you are actually using a 32 bits integers, that keeps count of the number of seconds since 1970-01-01 ; see Unix Time
That 32 bits number will overflow in 2038. That's the 2038 problem.
To solve that problem, you must not use a 32 bits UNIX timestamp to store your dates -- which means, when using MySQL, you should not use TIMESTAMP, but DATETIME (see 10.3.1. The DATETIME, DATE, and TIMESTAMP Types) :
The DATETIME type is used when you
need values that contain both date and
time information. The supported range
is '1000-01-01 00:00:00' to
'9999-12-31 23:59:59'.
The TIMESTAMP data type has a range
of '1970-01-01 00:00:01' UTC to
'2038-01-19 03:14:07' UTC.
The (probably) best thing you can do to your application to avoid/fix that problem is to not use TIMESTAMP, but DATETIME for the columns that have to contain dates that are not between 1970 and 2038.
One small note, though : there is a very high probably (statistically speaking) that your application will have been re-written quite a couple of times before 2038 ^^ So maybe, if you don't have to deal with dates in the future, you won't have to take care of that problem with the current version of your application...
A quick search on Google will do the trick: Year 2038 problem
The year 2038 problem (also known as Unix Millennium Bug, Y2K38 by analogy to the Y2K problem) may cause some computer software to fail before or in the year 2038
The problem affects all software and systems that store system time as a signed 32-bit integer, and interpret this number as the number of seconds since 00:00:00 UTC on January 1, 1970. The latest time that can be represented this way is 03:14:07 UTC on Tuesday, 19 January 2038. Times beyond this moment will "wrap around" and be stored internally as a negative number, which these systems will interpret as a date in 1901 rather than 2038
There is no easy fix for this problem for existing CPU/OS combinations, existing file systems, or existing binary data formats
http://en.wikipedia.org/wiki/Year_2038_problem has most of the details
In summary:
1) + 2) The problem is that many systems store date info as a 32-bit signed int equal to the number of seconds since 1/1/1970. The latest date that can be stored like this is 03:14:07 UTC on Tuesday, 19 January 2038. When this happens the int will "wrap around" and be stored as a negative number which will be interpreted as a date in 1901. What exactly will happen then, varies from system to system but suffice to say it probably won't be good for any of them!
For systems that only store dates in the past, then I guess you don't need to worry for a while! The main problem is with systems that work with dates in the future. If your system needs to work with dates 28 years in the future then you should start worrying now!
3) Use one of the alternative date formats available or move to a 64-bit system and use 64-bit ints. Or for databases use an alternative time stamp format (eg for MySQL use DATETIME)
4) See 3!
5) See 4!!! ;)
Bros, if you need to use PHP to display timestamps, this is the BEST PHP solution without changing from UNIX_TIMESTAMP format.
Use a custom_date() function. Inside it, use the DateTime. Here's the DateTime solution.
As long as you have UNSIGNED BIGINT(8) as your timestamps in database.
As long as you have PHP 5.2.0 ++
I was asking myself thses questions recently and want to share the solution I landed on for new projects.
Bigint
After reading variouse responses to questions like this one I found that storing a Unix timestamp in a Bigint column is a much better solution moving forward.
Bigints range will cover you from before the begining of time till the year 292277026596 wich may as well be called forever.
Pluss:
It uses the same 8bytes of storage that DATETIME uses.
Its timezone agnostic.
You can still use auto generated timestamps via DEFAULT (unix_timestamp())
range is so massive your server will turn into dust before wraparounds can happen, even if storing time in miliseconds.
DECIMAL
This is the solution I landed on as you get a bit more controll.
You can store an overkill date range like bigint or reduce it to something realistic and use less storage.
In my case I also want to store frations of a second as actual fractions, and I still wanted the timestamps gerated on insert.
Heres the column definition from my create table schema:
`created` decimal(18,2) NOT NULL DEFAULT (unix_timestamp(now(2))) COMMENT 'unix timestamp'
Using decimal(18,2) provides an absolutly overkill time range with the same storage as bigint/datetime while showing fractions of a second down to 2 digits.
Storage is based on the number of digits, 9 digits = 4bytes signed or unsigned it doesnt matter.
You could limit the range to something more realistic and use significantly less than datetime or increase the precision to nanoseconds. You decide whats important.
Another advantage is, if in the distant future you hit the limit of your range, Mysql will just tell you.
No wrap around issue will happen, instead you will get an error preventing the insertion and can easily alter the table again to add another digit.
This makes for a perfect sense to me I highly recommend starting new databases with this appraoch.
As I did't want to upgrade anything, I asked my backend (MSSQL) to do this job instead of PHP!
$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);
echo $row_tmp['next_date'];
May not be an efficient way, but it works.