Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
datetime.inc
1 <?php
39 function easy_datetime($then='')
40 {
41  // type verification
42  if (!is_int($then)) return 0;
43 
44  $now = time();
45  $now_date = date('Y-m-d');
46  $then_date = date('Y-m-d', $then);
47 
48  if ($then_date == $now_date) {
49  // today
50  return date('g:ia', $then).' today';
51  }
52  if ($then < $now) {
53  // time in the past
54  if ($then_date == date('Y-m-d', $now - 86400)) {
55  // yesterday
56  return date('g:ia', $then).' yesterday';
57  } else if ($now - $then < 604800) {
58  // less than a week ago
59  return date('g:ia', $then).' on '.date('l', $then);
60  }
61  } else {
62  // time in the future
63  if ($then_date == date('Y-m-d', $now + 86400)) {
64  // tomorrow
65  return date('g:ia', $then).' tomorrow';
66  } else if ($then - $now < 604800) {
67  // less than a week away
68  return date('g:ia', $then).' this '.date('l', $then);
69  }
70  }
71  // if we get to here it must be more than a week in either direction
72  return date('g:ia \o\n jS F Y', $then);
73 
74 }//end easy_datetime()
75 
76 
88 function easy_time_total($secs=0, $full_format=FALSE, $return_array=FALSE, $units=Array('d', 'h', 'm', 's'))
89 {
90  // type verification
91  if (!is_numeric($secs) || !is_bool($full_format) || !is_bool($return_array) || !is_array($units)) {
92  return '';
93  }
94 
95  if ($secs < 0) {
96  $suffix = ' ago';
97  $secs = abs($secs);
98  } else {
99  $suffix = '';
100  }
101 
102  $secs = $secs;
103 
104  $minute = 60;
105  $hour = 60 * $minute;
106  $day = 24 * $hour;
107 
108  $num_days = 0;
109  $num_hours = 0;
110  $num_minutes = 0;
111  $num_seconds = 0;
112 
113  // if there is more than one day left
114  if ($secs >= $day) {
115  $num_days = intval(floor($secs/$day));
116  // remove the number of seconds we have taken care of
117  $secs -= ($day * $num_days);
118  }
119 
120  // if there is more than one hour left
121  if ($secs >= $hour) {
122  $num_hours = intval(floor($secs/$hour));
123  // remove the number of seconds we have taken care of
124  $secs -= ($hour * $num_hours);
125  }
126 
127  // if there is more than one minute left
128  if ($secs >= $minute) {
129  $num_minutes = intval(floor($secs/$minute));
130  // remove the number of seconds we have taken care of
131  $secs -= ($minute * $num_minutes);
132  }
133 
134  $num_seconds = $secs;
135 
136  $str = '';
137 
138  // remove the values we dont want to show
139  if (!in_array('d', $units)) $num_days = 0;
140  if (!in_array('h', $units)) $num_hours = 0;
141  if (!in_array('m', $units)) $num_minutes = 0;
142  if (!in_array('s', $units)) $num_seconds = 0;
143 
144  // if they want the full string version
145  if ($full_format) {
146 
147  if ($num_days) {
148  $str .= $num_days.' day'.(($num_days > 1) ? 's' : '');
149  }
150 
151  if ($num_hours) {
152  // if there are no days don't need a joiner
153  if (!$num_days) {
154  $joiner = '';
155  } else if (!$num_minutes && !$num_seconds) {
156  // else if there aren't any minutes or seconds so join with " and "
157  $joiner = ' and ';
158  } else {
159  // else there must be more following join with a comma
160  $joiner = ', ';
161  }
162 
163  $str .= $joiner.$num_hours.' hour'.(($num_hours > 1) ? 's' : '');
164  }
165 
166  if ($num_minutes) {
167  // if there are no days or hours don't need a joiner
168  if (!$num_days && !$num_hours) {
169  $joiner = '';
170  } else if (!$num_seconds) {
171  // else if there aren't any seconds so join with " and "
172  $joiner = ' and ';
173  } else {
174  // else there must be more following so join with a comma
175  $joiner = ', ';
176  }
177 
178  $str .= $joiner.$num_minutes.' minute'.(($num_minutes > 1) ? 's' : '');
179  }
180 
181  if ($num_seconds) {
182  // if there are no days, hours or minutes don't need a joiner
183  if (!$num_days && !$num_hours && !$num_minutes) {
184  $joiner = '';
185  } else {
186  // else must be something preceding us so join with " and "
187  $joiner = ' and ';
188  }
189 
190  $str .= $joiner.$num_seconds.' second'.(($num_seconds > 1) ? 's' : '');
191  }
192 
193  } else if (!$return_array) {
194 
195  // they just want the normal "xx days xx:xx:xx xxxxx"
196 
197  $time_type = '';
198 
199  if ($num_days) {
200  $str .= $num_days.' day'.(($num_days > 1) ? 's' : '');
201  }
202 
203  if ($num_hours) {
204  // if there are no days don't need a joiner
205  if (!$num_days) {
206  $joiner = '';
207  } else if ($num_minutes || $num_seconds) {
208  // else we must be following the days so if there minutes or seconds we have a space
209  $joiner = ' ';
210  } else {
211  // else we must be following the days so but as there is no minutes or seconds we have " and "
212  $joiner = ' and ';
213  }
214 
215  if (!$num_minutes && !$num_seconds) {
216  $time_type = 'hour'.(($num_hours > 1) ? 's' : '');
217  } else {
218  $time_type .= 'h';
219  }
220 
221  $str .= $joiner.$num_hours;
222  }
223 
224  if ($num_minutes || ($num_hours && $num_seconds)) {
225 
226  // if there are no days or hours don't need a joiner
227  if (!$num_days && !$num_hours) {
228  $joiner = '';
229  } else if ($num_hours) {
230  // else if we are following hours, then have a colon
231  $joiner = ':';
232  } else if ($num_seconds) {
233  // else we must be following the days so if there seconds we have a space
234  $joiner = ' ';
235  } else {
236  // else we must be following the days so but as there is no seconds we have " and "
237  $joiner = ' and ';
238  }
239 
240  if (!$num_hours && !$num_seconds) {
241  $time_type = 'minute'.(($num_minutes > 1) ? 's' : '');
242  $str .= $joiner.$num_minutes;
243  } else {
244  $time_type .= $joiner.'m';
245  // if there are hours then zerofill to 2 places
246  if ($num_hours) {
247  $str .= $joiner.sprintf('%02d', $num_minutes);
248  } else {
249  $str .= $joiner.$num_minutes;
250  }
251  }
252  }
253 
254  if ($num_seconds) {
255  // if there are no days or hours don't need a joiner
256  if (!$num_days && !$num_hours && !$num_minutes) {
257  $joiner = '';
258  } else if ($num_hours || $num_minutes) {
259  // else if there hours the have a colon
260  $joiner = ':';
261  } else {
262  // else we must be following days, so just have a space
263  $joiner = ' and ';
264  }
265 
266  if (!$num_hours && !$num_minutes) {
267  $time_type = 'second'.(($num_seconds > 1) ? 's' : '');
268  $str .= $joiner.$num_seconds;
269  } else {
270  $time_type .= $joiner.'s';
271  $str .= $joiner.sprintf('%02d', $num_seconds);
272  }
273  }
274 
275  if ($time_type) {
276  $str .= ' '.((strstr($time_type, ':')) ? '('.trim($time_type).')' : trim($time_type));
277  }
278 
279  } else {
280 
281  // they want the numbers in array format
282  $return_value = Array('d' => 0, 'h' => 0, 'm' => 0, 's' => 0);
283 
284  if ($num_days) $return_value['d'] = $num_days;
285  if ($num_hours) $return_value['h'] = $num_hours;
286  if ($num_minutes) $return_value['m'] = $num_minutes;
287  if ($num_seconds) $return_value['s'] = $num_seconds;
288 
289  return $return_value;
290  }
291 
292  return $str.$suffix;
293 
294 }//end easy_time_total()
295 
296 
320 function easy_short_relative_datetime($timestamp, $with_day=TRUE)
321 {
322  if (is_numeric($timestamp) === FALSE) return FALSE;
323  $timestamp = (int)$timestamp;
324 
325  $current_time = time();
326  $time_diff = $current_time - $timestamp;
327  $duration_bits = easy_time_total(abs($time_diff), FALSE, TRUE);
328  $duration_text = '';
329  $add_ago = TRUE;
330 
331  if (empty($duration_bits) === FALSE) {
332  if (strtotime('-1 year', $current_time) > $timestamp) {
333  $years = (int)date('Y', $current_time) - (int)date('Y', $timestamp);
334  if (date('m-d H:i:s', $current_time) < date('m-d H:i:s', $timestamp)) {
335  $years--;
336  }
337  $duration_text = $years.' year';
338  if ($years !== 1) $duration_text .= 's';
339 
340  } else if (strtotime('-1 year', $timestamp) > $current_time) {
341  $years = (int)date('Y', $timestamp) - (int)date('Y', $current_time);
342  if (date('m-d H:i:s', $timestamp) < date('m-d H:i:s', $current_time)) {
343  $years--;
344  }
345  $duration_text = $years.' year';
346  if ($years !== 1) $duration_text .= 's';
347 
348  } else if (strtotime('-1 month', $current_time) > $timestamp) {
349  $months = 12 * ((int)date('Y', $current_time) - (int)date('Y', $timestamp));
350  $months += (int)date('m', $current_time) - (int)date('m', $timestamp);
351  if (date('d H:i:s', $current_time) < date('d H:i:s', $timestamp)) {
352  $months--;
353  }
354  $duration_text = $months.' month';
355  if ($months !== 1) $duration_text .= 's';
356 
357  } else if (strtotime('-1 month', $timestamp) > $current_time) {
358  $months = 12 * ((int)date('Y', $timestamp) - (int)date('Y', $current_time));
359  $months += (int)date('m', $timestamp) - (int)date('m', $current_time);
360  if (date('d H:i:s', $timestamp) < date('d H:i:s', $current_time)) {
361  $months--;
362  }
363  $duration_text = $months.' month';
364  if ($months !== 1) $duration_text .= 's';
365 
366  } else if (abs($time_diff) >= 14*86400) {
367  $duration_text = floor(abs($time_diff) / (7*86400)).' weeks';
368  } else if (($with_day === TRUE) && (abs(strtotime('00:00:00 today', $current_time) - strtotime('00:00:00 today', $timestamp)) < 7*86400)) {
369  return easy_datetime($timestamp);
370  } else {
371  reset($duration_bits);
372  $duration_text = '';
373 
374  // Get the first 'duration bit' that we can find that has a value
375  while (key($duration_bits) !== NULL) {
376  if (current($duration_bits) > 0) {
377  switch (key($duration_bits)) {
378  case 'd':
379  $duration_text = $duration_bits['d'].' day';
380  if ($duration_bits['d'] !== 1) $duration_text .= 's';
381  break;
382 
383  case 'h':
384  $duration_text = $duration_bits['h'].' hour';
385  if ($duration_bits['h'] !== 1) $duration_text .= 's';
386  break;
387 
388  case 'm':
389  $duration_text = $duration_bits['m'].' minute';
390  if ($duration_bits['m'] !== 1) $duration_text .= 's';
391  break;
392 
393  case 's':
394  $duration_text = $duration_bits['s'].' second';
395  if ($duration_bits['s'] !== 1) $duration_text .= 's';
396  break;
397 
398  }//emd switch
399  }//end if
400 
401  if ($duration_text !== '') {
402  break;
403  } else {
404  next($duration_bits);
405  }
406 
407  }//end while
408 
409  if (empty($duration_text) === TRUE) $duration_text = 'now';
410  }
411 
412  if ($add_ago === TRUE) {
413  if ($timestamp > $current_time) {
414  $duration_text .= ' in the future';
415  } else if ($timestamp < $current_time) {
416  $duration_text .= ' ago';
417  }
418  }
419 
420  }
421 
422  return $duration_text;
423 }
424 
425 
434 function readable_datetime($then=NULL)
435 {
436  return (is_null($then)) ? date('jS M Y g:ia') : date('jS M Y g:ia', $then);
437 
438 }//end readable_datetime()
439 
440 
449 function is_leap_year($year=NULL)
450 {
451  if (is_null($year)) $year = (int) date('Y');
452  if ($year % 4 != 0) return FALSE;
453 
454  // only 1 out of every four hundred year milestones is a leap year
455  if ($year % 100 == 0) return (($year / 100) % 4 == 0);
456 
457  return TRUE;
458 
459 }//end is_leap_year()
460 
461 
471 function days_in_month($month, $year)
472 {
473  if (is_null($month)) $month = (int) date('n');
474  if (is_null($year)) $year = (int) date('Y');
475 
476  switch ($month) {
477  case 2 : // Feb
478  return (is_leap_year($year)) ? 29 : 28;
479 
480  case 1 : // Jan
481  case 3 : // March
482  case 5 : // May
483  case 7 : // July
484  case 8 : // Aug
485  case 10 : // Oct
486  case 12 : // Dec
487  return 31;
488 
489  case 4 : // April
490  case 6 : // June
491  case 9 : // Sept
492  case 11 : // Nov
493  return 30;
494  default :
495  trigger_error('UNKNOWN MONTH : '.$month, E_USER_ERROR);
496  }//end switch
497 
498 }//end days_in_month()
499 
500 
514 function increment_date(&$day, &$month, &$year, $days_to_add=1)
515 {
516  if ($days_to_add < 0) {
517  decrement_date($day, $month, $year, -$days_to_add);
518  return;
519  }
520 
521  $day += $days_to_add;
522  while ($day > days_in_month($month, $year)) {
523  $day = $day - days_in_month($month, $year);
524  increment_month($month, $year);
525  }
526 
527 }//end increment_date()
528 
529 
543 function decrement_date(&$day, &$month, &$year, $days_to_sub=1)
544 {
545  if ($days_to_sub < 0) {
546  increment_date($day, $month, $year, -$days_to_sub);
547  return;
548  }
549 
550  $day = $day - $days_to_sub;
551  while ($day < 1) {
552  decrement_month($month, $year);
553  $day = days_in_month($month, $year) + $day;
554  }
555 
556 }//end decrement_date()
557 
558 
571 function increment_month(&$month, &$year, $months_to_add=1)
572 {
573  if ($months_to_add < 0) {
574  decrement_month($month, $year, -$months_to_add);
575  return;
576  }
577 
578  $month += $months_to_add;
579  while ($month > 12) {
580  $month = $month - 12;
581  $year++;
582  }
583 
584 }//end increment_month()
585 
586 
599 function decrement_month(&$month, &$year, $months_to_sub=1)
600 {
601  if ($months_to_sub < 0) {
602  increment_month($month, $year, -$months_to_sub);
603  return;
604  }
605 
606  $month = $month - $months_to_sub;
607  while ($month < 1) {
608  $month = 12 + $month;
609  $year--;
610  }
611 
612 }//end decrement_month()
613 
614 
624 function add_days_to_iso($iso, $days_to_add=1)
625 {
626  list($year,$month,$day) = sscanf($iso, '%04d-%02d-%02d');
627  increment_date($day, $month, $year, $days_to_add);
628  return sprintf('%04d-%02d-%02d', $year, $month, $day);
629 
630 }//end add_days_to_iso()
631 
632 
642 function add_months_to_iso($iso, $months_to_add=1)
643 {
644  list($year,$month) = explode('-', $iso);
645  increment_month($month, $year, $months_to_add);
646  return sprintf('%04d-%02d', $year, $month);
647 
648 }//end add_months_to_iso()
649 
650 
666 function days_between_isos($higher, $lower)
667 {
668  $higher_ts = iso8601_ts(substr($higher,0,10));
669  $lower_ts = iso8601_ts(substr($lower,0,10));
670 
671  // using round() to remove any one-hour
672  return round(($higher_ts - $lower_ts) / 86400);
673 
674 }//end days_between_isos()
675 
676 
685 function int_to_roman($num=0)
686 {
687  $conv = Array(
688  10 => Array('X', 'C', 'M'),
689  5 => Array('V', 'L', 'D'),
690  1 => Array('I', 'X', 'C'),
691  );
692  $roman = '';
693 
694  $num = (int) $num;
695 
696  $digit = (int) ($num / 1000);
697  $num -= $digit * 1000;
698  $roman = str_repeat('M',$digit);
699 
700  for ($i = 2; $i >= 0; $i--) {
701  $power = pow(10, $i);
702  $digit = (int) ($num / $power);
703  $num -= $digit * $power;
704 
705  if (($digit == 9) || ($digit == 4)) {
706  $roman .= $conv[1][$i].$conv[$digit+1][$i];
707  } else {
708  if ($digit >= 5) {
709  $roman .= $conv[5][$i];
710  $digit -= 5;
711  }
712 
713  while ($digit > 0) {
714  $roman .= $conv[1][$i];
715  $digit--;
716  }
717  }
718  }
719  return($roman);
720 
721 }//end int_to_roman()
722 
723 
735 function weekday_dates_in_month($weekday, $month, $year)
736 {
737  $day = mktime(0, 0, 0, (int) $month, 1, (int) $year);
738  $first_weekday = (int) date('w', $day);
739 
740  if ((int) $weekday < $first_weekday) {
741  $day_add = 7 - $first_weekday + (int) $weekday;
742  } else {
743  $day_add = (int) $weekday - $first_weekday;
744  }
745  $day = strtotime('+'.$day_add.' days', $day);
746 
747  $days = Array();
748  do {
749  $days[] = date('d', $day);
750  $day = strtotime('+1 week', $day);
751  } while ((int) date('n', $day) == $month);
752 
753  return $days;
754 
755 }//end weekday_dates_in_month()
756 
757 
770 function iso8601_date_component($iso8601)
771 {
772  if (!is_iso8601($iso8601)) return FALSE;
773  if (substr($iso8601,0,10) == '----------') {
774  return FALSE;
775  }
776  return substr($iso8601,0,10);
777 
778 }//end iso8601_date_component()
779 
780 
792 function iso8601_time_component($iso8601)
793 {
794  if (!is_iso8601($iso8601)) return FALSE;
795  if (strlen($iso8601) < 13) return FALSE;
796  if (substr($iso8601,11) == '--:--:--') return FALSE;
797  return substr($iso8601,11,8);
798 
799 }//end iso8601_time_component()
800 
801 
820 function is_iso8601($iso8601)
821 {
822  return (boolean)preg_match("/^\-?[0-9\-]{4}-[0-9\-]{2}-[0-9\-]{2}([ T]([0-9\-]{2}\:?){3}(Z|([+-]([0-9\-]{2}\:?){2}))?)?$/",$iso8601);
823 
824 }//end is_iso8601()
825 
826 
827 ?>