Other code examples of date being used
<?php
// set the default timezone to use. Available since PHP 5.1
date_default_timezone_set('UTC');
// Prints something like: Monday
echo date("l");
// Prints something like: Monday 8th of August 2005 03:12:46 PM
echo date('l jS \of F Y h:i:s A');
// Prints: July 1, 2000 is on a Saturday
echo "July 1, 2000 is on a " . date("l", mktime(0, 0, 0, 7, 1, 2000));
/* use the constants in the format parameter */
// prints something like: Wed, 25 Sep 2013 15:28:57 -0700
echo date(DATE_RFC2822);
// prints something like: 2000-07-01T00:00:00+00:00
echo date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
?>
Things to be aware of when using week numbers with years.
<?php
echo date("YW", strtotime("2011-01-07")); echo date("YW", strtotime("2011-12-31")); echo date("YW", strtotime("2011-01-01")); ?>
BUT
<?php
echo date("oW", strtotime("2011-01-07")); echo date("oW", strtotime("2011-12-31")); echo date("oW", strtotime("2011-01-01")); ?>
Reason:
Y is year from the date
o is ISO-8601 year number
W is ISO-8601 week number of year
Conclusion:
if using 'W' for the week number use 'o' for the year.
If you have a problem with the different time zone, this is the solution for that.
<?php
$defaultTimeZone='UTC';
if(date_default_timezone_get()!=$defaultTimeZone)) date_default_timezone_set($defaultTimeZone);
function _date($format="r", $timestamp=false, $timezone=false)
{
$userTimezone = new DateTimeZone(!empty($timezone) ? $timezone : 'GMT');
$gmtTimezone = new DateTimeZone('GMT');
$myDateTime = new DateTime(($timestamp!=false?date("r",(int)$timestamp):date("r")), $gmtTimezone);
$offset = $userTimezone->getOffset($myDateTime);
return date($format, ($timestamp!=false?(int)$timestamp:$myDateTime->format('U')) + $offset);
}
echo 'System Date/Time: '.date("Y-m-d | h:i:sa").'<br>';
echo 'New York Date/Time: '._date("Y-m-d | h:i:sa", false, 'America/New_York').'<br>';
echo 'Belgrade Date/Time: '._date("Y-m-d | h:i:sa", false, 'Europe/Belgrade').'<br>';
echo 'Belgrade Date/Time: '._date("Y-m-d | h:i:sa", 514640700, 'Europe/Belgrade').'<br>';
?>
This is the best and fastest solution for this problem. Working almost identical to date() function only as a supplement has the time zone option.
this how you make an HTML5 <time> tag correctly
<?php
echo '<time datetime="'.date('c').'">'.date('Y - m - d').'</time>';
?>
in the "datetime" attribute you should put a machine-readable value which represent time , the best value is a full time/date with ISO 8601 ( date('c') ) ,,, the attr will be hidden from users
and it doesn't really matter what you put as a shown value to the user,, any date/time format is okay !
This is very good for SEO especially search engines like Google .
If timestamp is a string, date converts it to an integer in a possibly unexpected way:
<?php
echo (int)'0x10'; echo intval('0x10'); echo date('s', '0x10'); echo date('s', '010'); ?>
(PHP 5.6.16)
I just wanted to emphasise that the return value of date( ) is a string, even when the result of your date format string is a number, such as "j" -> a number 1 to 31, or 'N' -> a day number 1 for Monday through 7 for Sunday... it's still returned as a string! "1" or "7" or "31". This is much more obvious on the "zero-padded" results, but it's worth repeating.
If you aren't careful, you can get stuck in a while loop comparing days of the week with something like:
<?php
while ( date('N', $time ) !== 7 ) {
$time = $time - 86400;
}
?>
... for example. The result of date( ) should be cast to an int for numeric comparison with the exact equality operator:
<?php
while ( (int)date('N', $time ) !== 7 ) {
$time = $time - 86400;
}
?>
Wasted an hour today on that silly mistake.
Thanks to tcasparr at gmail dot com for the great idea (at least for me) ;)
I changed the code a little to replicate the functionality of date_parse_from_format, once I don't have PHP 5.3.0 yet. This might be useful for someone. Hope you don't mind changing your code tcasparr at gmail dot com.
<?php
function dateParseFromFormat($stFormat, $stData)
{
$aDataRet = array();
$aPieces = split('[:/.\ \-]', $stFormat);
$aDatePart = split('[:/.\ \-]', $stData);
foreach($aPieces as $key=>$chPiece)
{
switch ($chPiece)
{
case 'd':
case 'j':
$aDataRet['day'] = $aDatePart[$key];
break;
case 'F':
case 'M':
case 'm':
case 'n':
$aDataRet['month'] = $aDatePart[$key];
break;
case 'o':
case 'Y':
case 'y':
$aDataRet['year'] = $aDatePart[$key];
break;
case 'g':
case 'G':
case 'h':
case 'H':
$aDataRet['hour'] = $aDatePart[$key];
break;
case 'i':
$aDataRet['minute'] = $aDatePart[$key];
break;
case 's':
$aDataRet['second'] = $aDatePart[$key];
break;
}
}
return $aDataRet;
}
?>
Also, if you need to change the format of dates:
<?php
function changeDateFormat($stDate,$stFormatFrom,$stFormatTo)
{
$date = dateParseFromFormat($stFormatFrom,$stDate);
return date($stFormatTo,mktime($date['hour'],
$date['minute'],
$date['second'],
$date['month'],
$date['day'],
$date['year']));
}
?>
If you want to use HTML5's <date> tag, the following code will generate the machine-readable value for the 'datetime' attribute:
<?php
function getDateTimeValue( $intDate = null ) {
$strFormat = 'Y-m-d\TH:i:s.uP';
$strDate = $intDate ? date( $strFormat, $intDate ) : date( $strFormat ) ;
return $strDate;
}
echo getDateTimeValue();
?>
FYI: there's a list of constants with predefined formats on the DateTime object, for example instead of outputting ISO 8601 dates with:
<?php
echo date('c');
?>
or
<?php
echo date('Y-m-d\TH:i:sO');
?>
You can use
<?php
echo date(DateTime::ISO8601);
?>
instead, which is much easier to read.
<?php
function strftimeFormatToDate($strftimeFormat) {
$caracs = array(
"%d" => "d",
"%a" => "D",
"%e" => "j",
"%A" => "l",
"%u" => "N",
"%w" => "w",
"%j" => "z",
"%V" => "W",
"%B" => "F",
"%m" => "m",
"%b" => "M",
"%G" => "o",
"%Y" => "Y",
"%y" => "y",
"%P" => "a",
"%p" => "A",
"%l" => "g",
"%I" => "h",
"%H" => "H",
"%M" => "i",
"%S" => "s",
"%z" => "O",
"%Z" => "T",
"%s" => "U",
);
return strtr((string)$strftimeFormat, $caracs);
}
$strftimeFormat = '%Y-%m-%d %H:%M:%S';
$formatDate = strftimeFormatToDate($strftimeFormat); ?>
Here's my solution for looking up the month number by name (used when parsing an 'ls'):
<?php
for($m=1;$m<=12;$m++){
$month=date("M",mktime(0,0,0,$m,1,2000));
$mon["$month"]=$m;
}
?>
It's common for us to overthink the complexity of date/time calculations and underthink the power and flexibility of PHP's built-in functions. Consider http://php.net/manual/en/function.date.php#108613
<?php
function get_time_string($seconds)
{
return date('H:i:s', strtotime("2000-01-01 + $seconds SECONDS"));
}
In order to determine if a year is a leap year an earlier poster suggested simply checking to see if the year is a multiple of four:
<?php
function is_leapyear_broken($year = 2004) {
return ($year%4)==0;
}
?>
While this will work for the majority of years it will not work on years that are multiples of 100 but not multiples of 400 i.e.(2100).
A function not using php's date() function that will also account for this small anomaly in leap years:
<?php
function is_leapyear_working($year = 2004) {
if((($year%4==0) && ($year%100!=0)) || $year%400==0) {
return true;
}
return false;
}
?>
While is_leapyear_working will not return true for the few non-leap years divisible by four I couldn't tell you if this is more or less efficient than using php's date() as an even earlier poster suggested:
<?php
function is_leapyear($year = 2004) {
$is_leap = date('L', strtotime("$year-1-1"));
return $is_leap;
}
?>
Correct format for a MySQL DATETIME column is
<?php $mysqltime = date ("Y-m-d H:i:s", $phptime); ?>
The following function will return the date (on the Gregorian calendar) for Orthodox Easter (Pascha). Note that incorrect results will be returned for years less than 1601 or greater than 2399. This is because the Julian calendar (from which the Easter date is calculated) deviates from the Gregorian by one day for each century-year that is NOT a leap-year, i.e. the century is divisible by 4 but not by 10. (In the old Julian reckoning, EVERY 4th year was a leap-year.)
This algorithm was first proposed by the mathematician/physicist Gauss. Its complexity derives from the fact that the calculation is based on a combination of solar and lunar calendars.
<?php
function getOrthodoxEaster($date){
$year = date("Y", $date);
$r1 = $year % 19;
$r2 = $year % 4;
$r3 = $year % 7;
$ra = 19 * $r1 + 16;
$r4 = $ra % 30;
$rb = 2 * $r2 + 4 * $r3 + 6 * $r4;
$r5 = $rb % 7;
$rc = $r4 + $r5;
return strtotime("3 April $year + $rc days");
}
?>
I've been flicking through the comments looking for some succinct date code and have noticed an alarming number of questions and over-burdened examples related to date mathematics. One of the most useful skills you can utilize when performing date math is taking full advantage of the UNIX timestamp. The UNIX timestamp was built for this kind of work.
An example of this relates to a comment made by james at bandit-dot-co-dot-en-zed. James was looking for a way to calculate the number of days which have passed since a certain date. Rather than using mktime() and a loop, James can subtract the current timestamp from the timestamp of the date in question and divide that by the number of seconds in a day:
<?php
$days = floor((time() - strtotime("01-Jan-2006"))/86400);
print("$days days have passed.\n");
?>
Another usage could find itself in a class submitted by Kyle M Hall which aids in the creation of timestamps from the recent past for use with MySQL. Rather than the looping and fine tuning of a date, Kyle can use the raw UNIX timestamps (this is untested code):
<?php
$ago = 14; $timestamp = time() - ($ago * 86400);
?>
Hopefully these two examples of "UNIX-style" timestamp usage will help those finding date mathematics more elusive than it should be.
I use the function below to calculate the Unix timestamp of the start of a week. It includes a boolean flag to request a GMT offset instead of the current locale setting.
<?php
function getWeekOffsetTimestamp($year, $week, $useGmt = false) {
if ($useGmt) {
$timezoneSettingBackup = date_default_timezone_get();
date_default_timezone_set("GMT");
}
$halfwayTheWeek = strtotime($year."0104 +".($week - 1)." weeks");
$dayOfTheWeek = date("N", $halfwayTheWeek);
$daysToSubtract = $dayOfTheWeek - 1;
$unixTimestamp = strtotime("-$daysToSubtract day", $halfwayTheWeek);
if ($useGmt) {
date_default_timezone_set($timezoneSettingBackup);
}
return $unixTimestamp;
}
?>
This function will add working day to a given timestamp
<?php
function addworkinday($timestamp,$daystoadd){
$dayoftheweek = date("N",$timestamp);
$sum =$dayoftheweek +$daystoadd;
while ($sum >= 6) {
$daystoadd=$daystoadd+1;
$sum=$sum-1;
}
return $timestamp +(60*60*24*$daystoadd);
}
?>
Most spreadsheet programs have a rather nice little built-in function called NETWORKDAYS to calculate the number of business days (i.e. Monday-Friday, excluding holidays) between any two given dates. I couldn't find a simple way to do that in PHP, so I threw this together. It replicates the functionality of OpenOffice's NETWORKDAYS function - you give it a start date, an end date, and an array of any holidays you want skipped, and it'll tell you the number of business days (inclusive of the start and end days!) between them.
I've tested it pretty strenuously but date arithmetic is complicated and there's always the possibility I missed something, so please feel free to check my math.
The function could certainly be made much more powerful, to allow you to set different days to be ignored (e.g. "skip all Fridays and Saturdays but include Sundays") or to set up dates that should always be skipped (e.g. "skip July 4th in any year, skip the first Monday in September in any year"). But that's a project for another time.
<?php
function networkdays($s, $e, $holidays = array()) {
if ($s > $e)
return networkdays($e, $s, $holidays);
$sd = date("N", $s);
$ed = date("N", $e);
$w = floor(($e - $s)/(86400*7)); if ($ed >= $sd) { $w--; } $nwd = max(6 - $sd, 0); $nwd += min($ed, 5); $nwd += $w * 5; foreach ($holidays as $h) {
$h = strtotime($h);
if ($h > $s && $h < $e && date("N", $h) < 6)
$nwd--;
}
return $nwd;
}
$start = strtotime("1 January 2010");
$end = strtotime("13 December 2010");
$holidays = array();
$holidays[] = "4 July 2010"; $holidays[] = "6 September 2010"; echo networkdays($start, $end, $holidays); ?>
Or, if you just want to know how many work days there are in any given year, here's a quick function for that one:
<?php
function workdaysinyear($y) {
$j1 = mktime(0,0,0,1,1,$y);
if (date("L", $j1)) {
if (date("N", $j1) == 6)
return 260;
elseif (date("N", $j1) == 5 or date("N", $j1) == 7)
return 261;
else
return 262;
}
else {
if (date("N", $j1) == 6 or date("N", $j1) == 7)
return 260;
else
return 261;
}
}
?>
When using 'U' to return a UNIX time stamp, you may not get what you expect. In the following example, we try to get the current Unix time stamp for a user in a different timezone.
<?php
$timezone = new \DateTimeZone($userTimeZone);
$date = new \DateTime('@' . time(), $timezone);
$date->setTimezone($timezone);
$now = $date->format('U');
?>
$now will return the same (the server's current) Unix time stamp regardless which timezone your user is in.
To get the actual Unix time stamp based on a time zone, replace format('U') as in the following example;
<?php
$timezone = new \DateTimeZone($userTimeZone);
$date = new \DateTime('@' . time(), $timezone);
$date->setTimezone($timezone);
$now = $date->getTimestamp() + $date->getOffset();
?>
To quickly convert date("N") to a 0 based index with Sunday being represented as 0, you can run it against modulus 7:
<?php
$first_of_month_index = date('N', strtotime('4/1/1990')) % 7;
?>
To actually make use ot the "u" (microsecond) you need to use the DateTime object and not the date() function.
For example
<?php
$t = microtime(true);
$micro = sprintf("%06d",($t - floor($t)) * 1000000);
$d = new DateTime( date('Y-m-d H:i:s.'.$micro,$t) );
print $d->format("Y-m-d H:i:s.u");
?>
Here is a cool Date class to implement the date function:
<?php
class Date
{
private $shortDateFormat = "F j, Y";
private $longDateFormat = "F j, Y, g:i a";
private $timestamp = 0;
function __construct($timestamp = 0)
{
$this->timestamp = $timestamp;
}
public function getTime()
{
return (int) $this->timestamp;
}
public function long()
{
if ( $this->timestamp > 0 )
{
return date ( $this->longDateFormat , $this->timestamp );
}
else
{
return "";
}
}
public function short()
{
if ( $this->timestamp > 0 )
{
return date ( $this->shortDateFormat , $this->timestamp );
}
else
{
return "";
}
}
public function __toString()
{
return $this->timestamp;
}
}
?>
Use this to convert the local/UTC hour to the UTC/local hour:
<?php
for($utc_to_local = array(), $offset = date('Z'), $h = 0; $h < 24; $utc_to_local[] = date('G', mktime($h++)+$offset));
$local_to_utc = array_flip($utc_to_local);
echo "2 am local is ", $local_to_utc[2], " UTC";
echo "3 pm UTC is ", $utc_to_local[15], " local";
?>
This is useful when you need to do many conversions. Lookup tables are faster than calling date() and mktime() multiple times.
If you want to compare this week with the same week last year, here is some code to get you the time at the beginning of the week. You can then add days, hours, etc to get to the day of the week that you want to know about.
<?php
$time_passed = (date('N')-1)* 24 * 3600; $startOfWeek = mktime(0,0,0,date('m'),date('d'),date('Y')) - $time_passed;
$lastyear = $startOfWeek - 365*24*3600;
$weekdiff = date('W') - date('W',$lastyear);
if($weekdiff != 0)
{
$lastyear = $lastyear + ($weekdiff*7*24*3600);
}
$lastyear_time_passed = (date('N',$lastyear)-1) * 24 * 3600; $startOfWeek_lastyear = mktime(0,0,0,date('m',$lastyear),date('d',$lastyear),date('Y',$lastyear)) - $lastyear_time_passed;
?>
So now you have the unix time for the start of this week ($startOfWeek), and the start of the same week last year ($startOfWeek_lastyear).
You can convert back to datetime format easily:
<?php
echo date('Y-m-d H:i:s',$startOfWeek).'<br>';
echo date('Y-m-d H:i:s',$startOfWeek_lastyear).'<br><br>';
echo date('l F jS, Y',$startOfWeek).'<br>';
echo date('l F jS, Y',$startOfWeek_lastyear);
?>
Not sure why this got ignored the first time, but this is an even simpler way to check leap year:
<?php
function isLeapYear($year)
{ return ((($year%4==0) && ($year%100)) || $year%400==0) ? (true):(false); }
?>
Sometimes it is very useful to convert a sql timestamp to an also called NTP time. This is often used as time date notation in XML RSS pages. To convert a timestamp to this NTP notation try the following:
<?php
echo date('D, d M Y h:i:s O', strtotime ($timestamp);
?>
If anyone needs a really fast function for converting a datetime string (i.e. as retrieved from a MySQL DATETIME entry) into a human-friendly time output analogous to date($format, $time), here's a useful function.
<?php
function fdate($datetimestring = '1970-01-01 00:00:00', $format = 'U') {
$dt = new DateTime($datetimestring);
return $dt->format($format);
}
?>
The main purpose of this is to reduce lines of code and allow inline coding. For example:
<?php
echo "This page was submitted on ".fdate($row['created'], 'F j, Y g:i:s A')." and last modified ".fdate($row['modified'], 'F j, Y g:i:s A')."<br />\n";
?>
<?php
?>
<h2>PHP 2038 date bug demo (php version <?php echo phpversion(); ?>)</h1>
<div style='float:left;margin-right:3em;'>
<h3>OLD Buggy date()</h3>
<?php
$format='F j, Y';
for ( $i = 1900; $i < 2050; $i++) {
$datep = "$i-01-01";
?>
Trying: <?php echo $datep; ?> = <?php echo date($format, strtotime($datep)); ?><br>
<?php
}
?></div>
<div style='float:left;'>
<h3>NEW DateTime Class (v 5.2+)</h3><?php
for ( $i = 1900; $i < 2050; $i++) {
$datep = "$i-01-01";
$date = new DateTime($datep);
?>
Trying: <?php echo $datep; ?> = <?php echo $date->format($format); ?><br>
<?php
}
?></div>
I needed to convet a duration timestamp into H:i:s but whenever I did it kept bringing 5 back as 01:00:05 (due to some DST stuff) so I made this function to replace date(). It has no optimisations but hopefully someone might find it useful:
<?php
function get_time_string(){
$time = 3600+(60*32)+(50); $time_string = '';
$hours = (int)($time/(60*60));
if(strlen($hours) > 1){
$time_string = $hours.':';
}else{
$time_string = '0'.$hours.':';
}
$minutes = (int)(($time%(60*60))/(60));
if($minutes >= 1){
if(strlen($minutes) > 1){
$time_string .= $minutes.':';
}else{
$time_string .= '0'.$minutes.':';
}
$seconds = ($time%(60*60))%(60);
if(strlen($seconds) > 1){
$time_string .= $seconds;
}else{
$time_string .= '0'.$seconds;
}
}else{
if(strlen($time) > 1){
$time_string .= '00:'.$time;
}else{
$time_string .= '00:0'.$time;
}
}
return $time_string;
}
?>
<?php
function mdate($format, $microtime = null) {
$microtime = explode(' ', ($microtime ? $microtime : microtime()));
if (count($microtime) != 2) return false;
$microtime[0] = $microtime[0] * 1000000;
$format = str_replace('u', $microtime[0], $format);
return date($format, $microtime[1]);
}
?>
echo mdate('Y-m-d H:i:s.u');
2014-05-19 12:41:59.202303
<?php
$day=date("l");
$date=date("j");
$suffix=date("S");
$month=date("F");
$year=date("Y");
echo $day . ", " . $month . " " . $date . $suffix . ", " . $year;
?>
rudimentary, simple way to due things, but it gets the job done for someone learning more on the subject.