I am using PHP and jQuery to build an interactive timeline which needs to display dates between 1500 and 2020. I usually use PHP's strtotime function when working with dates, but it does not work for dates pre-1900.
The dates will come from a MySQL database, and are formatted as strings such as "January 31, 1654" (this may not be the ideal format, but I can't change how they are stored). I am using PHP to parse the dates, basically converting them into pixel values which determine where they are displayed on the timeline.
What is the easiest way to parse these historical dates?
The DateTime class, here, might help (quoting):
Each component of date (e.g. year) is
internally stored as 64-bit number so
all imaginable dates (including
negative years) are supported.
But note that:
It's only exists in PHP >= 5.2
And several methods only exist in PHP >= 5.3
So: beware of which methods you're using, if you're developping on PHP 5.3 and want your software to be compatible with PHP 5.2
Another solution (especially, if using Zend Framework in your application) would be the Zend_Date component (quoting):
Although PHP 5.2 docs state, "The
valid range of a timestamp is
typically from Fri, 13 Dec 1901
20:45:54 GMT to Tue, 19 Jan 2038
03:14:07 GMT," Zend_Date supports a
nearly unlimited range, with the help
of the BCMath extension
Using the wonderful Carbon Library, dates in the past are not a problem:
$date = Carbon::now();
$date->subCenturies(23);
echo $date->format('Y-m-d');
// -0282-03-15
This works for dates where humans have been around. For everything else, using a date (with day and month, set on the AC/BC scale) does not make a lot of sense.
Related
Am using the strtotime function to find the difference between two given dates like this:
$diff_in_mill_seconds = strtotime($ToDate) - strtotime($FromDate);
$difference_in_years = round($diff_in_mill_seconds / (365*60*60*24),1);
This script fails when the $ToDate is beyond 2038-01-19.
The official PHP Documentation says:
The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC
The PHP Documentation also says:
Using this function for mathematical operations is not advisable. It is better to use DateTime::add() and DateTime::sub() in PHP 5.3 and later, or DateTime::modify() in PHP 5.2.
I cannot use DateTime::add() and DateTime::sub() as the PHP version on the server is 5.2.
So, how do I calculate the difference between two dates (beyond 2038-01-19) in years using php 5.2?
It's the UNIX Y2K38 bug. It has been fixed in 64bit implementations of PHP or by using DateTime::diff, which does not use integers internally and hence does not suffer from the problem.
You need either. There's no real fix without switching platforms.
I wrote an application in PHP that connects to a SQL server.
If this application runs on windows it uses srvsql libraries, in linux case it uses sybase libraries.
My trouble is that date fields outputs of sql server are not the same, with srvsql i get something like '2012-12-10 12:14:26.067'. With sybase i get 'Dec 10 2012 12:14:26:067PM '!
How can i set sybase connection to get the SAME output format without changing every query?
I've been looking for a good solution to this for a few hours now myself. While I would love to handle this php side it just isn't an option in my current case as a 3rd party library is processing the data. The solution I just stumbled upon is on the query side.
The rough idea is convert the date to a string before the results are returned so the libraries (mssql and sqlsrv in my case) don't have the opportunity to muk with the results.
CONVERT(nvarchar(30), myDate, 121) AS date
121 is yyyy-mm-dd hh:mi:ss.mmm(24h)
Other options can be found in Microsoft's documentation.
Edit
Found this the other day. Haven't experimented with it but the mssql library has a setting to tell it what to do with dates: mssql.datetimeconvert = On. There may be a way in php.ini to make both libraries render the date in the same format. I'm too far into the convert solution to switch over now but it would be worth some experimentation if someone is reading this for the first time.
Instead of worrying about the date format that comes back from the different databases, consider handling it PHP-side.
Both of those formats, (2012-12-10 12:14:26.067 and Dec 10 2012 12:14:26:067PM) are recognized by PHP. When passed into a DateTime object, they work as expected. From the PHP interactive prompt:
php > $dt = new DateTime('Dec 10 2012 12:14:26:067PM');
php > echo $dt->format('r u'), "\n";
Mon, 10 Dec 2012 12:14:26 -0800 067000
php >
php > $dt = new DateTime('2012-12-10 12:14:26.067');
php > echo $dt->format('r u'), "\n";
Mon, 10 Dec 2012 12:14:26 -0800 067000
If you need a refresher, r is the format code for an RFC 2822 date, while u is the format code for microseconds, which only work with DateTimes.
By switching to DateTimes, you can easily juggle between input formats and basically never have to worry about it. DateTime uses the strtotime parsing rules. You'll want to understand their limitations, but you generally won't bump up against them.
I'm creating a mobile version of a website. On the normal version we just use a jquery date picker to select the date. I haven't added anything like this yet on the mobile version because It seemed my Iphone was smart enough to realise it was a date field and give you date scrollers.
But after I've selected the date it's coming up at 7 Aug 2012 which raises a few questions for me... is this standard? or am I going to have to code for different date formats coming from different phones?
Would it be best to use a jquery date picker? (I'm not sure this would be very tidy).
What's the best way to convert a date like this into a format that php and my database can handle. I have done a bit of looking around google but haven't found much as of yet.
Try this
<?php
$today = date('Y-m-d', strtotime('7 Aug 2012'));
echo $today;
?>
gives 2012-08-07
You can change its output by altering Y-m-d in date()
Refer this!
$date = DateTime::createFromFormat('j M Y', '7 Aug 2012'); is the most robust way to do it if you know the format. strtotime guesses which isn't necessarily a good thing, and you won't be informed (i.e. an exception won't be thrown) if the date is in a bad format.
See the manual here: http://www.php.net/manual/en/datetime.createfromformat.php
I don't think the date format is standard. It is very probable that it is affected by the user settings (eg. locale). Eg. if the user defines a Portuguese locale I think the date would be a little bit different.
Using jquery date picker you have the advantage of being able to specify your desired format (applying the dateFormat option). Then you could safely write a PHP script that reads the date in your defined format. You can use PHP's date() function as specified by #Bhuvan Rikka.
Good evŠµning!
echo date('r', strtotime('10.01.11'));
Prints: Sun, 05 Feb 2012 10:01:11
Expected: Mon, 10 Jan 2011 00:00:00
How do I force strtotime() to parse the input string as a date only? I have to convert a bunch of dates in different format. DateTime::format is not an option since I don't know all the formats the script will run into, and it's not even installed on the server (and i don't have privileges to do it).
Tried
strtotime('day 10.01.11'),
strtotime('10.01.11 00:00:00'),
strtotime('10.01.11 midnight')
- nothing worked.
Any help is much appreciated
How do I force strtotime() to parse the input string as a date only?
You don't. strtotime uses very well-defined parsing formats. What it generates will depend entirely on what you give it.
'10.01.11' is parsed as a time format, as it will always interpret three pairs of digits separated by periods as a time. It will recognize dates when separated by dashes, slashes or spaces. Annoyingly, there's an example there on the date format page that uses dots, but there doesn't seem to be a sure-fire way to force date parsing instead of time parsing. Sigh, PHP.
If you need that specific format to be interpreted as a date instead of a time, you have two options.
First, you can use a different date parsing method. If the expected format never changed, you could use DateTime::createFromFormat() or the horrifying strptime. You've indicated in comments that the format will vary and your PHP version is old enough not to have DateTime, so this might not work for you.
Second, you can pre-process the data. At least in this example, a conversion of . to / may do the trick, though 10/01/11 can be ambiguous as a date to humans. There's nothing wrong with a little regex sniffing to determine how to best process data.
There's also a third option: if you're getting this information from users, make your application begin forcing users to enter dates in a normal, consistent, parseable format. It may take some time to train your users to use YYYY-MM-DD, but it's probably the most sane long-term bet.
Is modifying the input an option for you?
$str = '10.01.11';
$str = str_replace('.', '/', $str);
echo date('r', strtotime($str));
However, this will still output Sat, 01 Oct 2011 00:00:00, according to the MM.DD.YY pattern (US standard).
EDIT: Depending on you usage, you might consider creating a list of regex patterns and parse the date accordingly. It is very hard to make a code like this to be open to all possibilities.
Tested, this works:
$date = DateTime::createFromFormat('d.m.y', '10.01.11');
echo $date->format('r');
http://codepad.viper-7.com/OH7Kyn
why don't you add the time set to 00:00:00 by default?
e.g.
echo date('D, d M Y H:i:s', strtotime('10.01.11'));
also strtotime uses the american date format so this will be translated into 1st of october 2011. it's easier to use the iso date format
I don't think strtotime knows how to parse those dates. To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates.
I need to calculate the number of decades between 2 dates possible spanning form 1708 until today - the limitations are as far as I can gather are 1970/1901 within PHP native functions.
Can anyone advise?
Thanks!
If you have PHP >= 5.3.0:
$before = new DateTime('1708-02-02');
$decades = $before->diff(new DateTime())->y / 10;
You could use Zend_Date. It's part of the Zend Framework but can be used standalone, you don't need to install the whole framework to use it. It can work with dates beyond 1901 if the bcmath extension is installed into your PHP. From Zend_date's theory of operation:
This was only possible, because Zend_Date is not limited to UNIX timestamps nor integer values. The BCMath extension is required to support extremely large dates outside of the range Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT. Additional, tiny math errors may arise due to the inherent limitations of float data types and rounding, unless using the BCMath extension.
I like to recommend Zend components because they are well-groomed, high-quality code. There are other solutions to this, though, for example using the mySQL date functions.
I would write a custom method.
PHP date functions are based on the epoch ( 1969 ) so there won't be much help there.
If your just looking at years that is simple math
higher year - earlier year = years
years / 10 = decades.
If you mean decades from an even 01-10, 11-20 then you could do some rounding. (round early date up, later date down to nearest 10.