PHP Classes

File: Time_When.php

Recommend this page to a friend!
  Classes of Martin   Text to Timestamp   Time_When.php   Download  
File: Time_When.php
Role: Class source
Content type: text/plain
Description: Source
Class: Text to Timestamp
Convert English expressions into time values
Author: By
Last change:
Date: 14 years ago
Size: 11,011 bytes
 

Contents

Class file image Download
<?php /** * @package Time * @copyright Copyright (c) 2009, Martin Aarhof * @version 1.0 */ /** * A class to get those nice "just a moment ago", "1 day ago" or "6 hours ago", instead of a simple timestamp. * This can also be reconfigured for own use. * * @todo Better way to count time diff. * - Maybe fx. it should use fx. "2 month ago" instead of "1 month ago" when its "1 month + 30 days or so" ? * - GET RID OF THAT SWITCH {@link getUnit()} * - Implement so endtime can be higher than starttime (+ days) * * @package Time_When * */ class Time_When { const EQUALS = '=='; const LESS_THAN = '<'; const HIGHER_THAN = '>'; /** * Placeholder for our types, can be added at {@link addType()} and removed by {@link removeType()} * @var array */ protected $types = array(); /** * Placeholder for our timers can be added at {@link addTimer()} * @var array */ protected $timer = array(); /** * Identifier to text in type * @var string */ public $textAssigner = '?'; /** * Text to replace with the time from the type * @var string */ public $textReplacer = '[NUM]'; /** * Constructor, in this you can set some default types. */ public function __construct() { $this->types = array( /* Commented out, until +days works! '+sec' => array('time' => 60, 'text' => 'almost right away'), '+min' => array('time' => (60*60), 'text' => '? ?', 'assign' => array('[NUM]', array(self::LESS_THAN, 2, 'minute', 'minutes'))), '+hour' => array('time' => (60*60*60), 'text' => '? ?', 'assign' => array('[NUM]', array(self::EQUALS, 1, 'hour', 'hours'))), '+day' => array('time' => (60*60*60*24), 'text' => '? ?', 'assign' => array('[NUM]', array(self::HIGHER_THAN, 1, 'days', 'day'))), '+month' => array('time' => (60*60*60*24*30), 'text' => '? ?', 'assign' => array('[NUM]', array(self::EQUALS, 1, 'month', 'months'))), '+year' => array('time' => (60*60*60*24*30*12), 'text' => '? ?', 'assign' => array('[NUM]', array(self::EQUALS, 1, 'year', 'years'))), */ 'now' => array('time' => 0, 'text' => 'Just now!'), '-sec' => array('time' => -60, 'text' => 'moments ago'), '-min' => array('time' => -(60*60), 'text' => $this->textAssigner . ' ' . $this->textAssigner . ' ago', 'assign' => array($this->textReplacer, array(self::LESS_THAN, 2, 'minute', 'minutes'))), '-hour' => array('time' => -(60*60*60), 'text' => $this->textAssigner . ' ' . $this->textAssigner . ' ago', 'assign' => array($this->textReplacer, array(self::EQUALS, 1, 'hour', 'hours'))), '-day' => array('time' => -(60*60*60*24), 'text' => $this->textAssigner . ' ' . $this->textAssigner . ' ago', 'assign' => array($this->textReplacer, array(self::HIGHER_THAN, 1, 'days', 'day'))), '-month' => array('time' => -(60*60*60*24*30), 'text' => $this->textAssigner . ' ' . $this->textAssigner . ' ago', 'assign' => array($this->textReplacer, array(self::EQUALS, 1, 'month', 'months'))), '-year' => array('time' => -(60*60*60*24*30*12), 'text' => $this->textAssigner . ' ' . $this->textAssigner . ' ago', 'assign' => array($this->textReplacer, array(self::EQUALS, 1, 'year', 'years'))), '-galaxy' => array('time' => -(60*60*60*24*30*12*200), 'text' => 'Long, long time ago... in a far far galaxy'), ); } /** * Method to add new types {@link types} to our conversion. * $name HAS TO BE UNIQUE! * * @example example.php 0 38 * @param string $name a unique identifier * @param array $options - $options['time'] and $options['text'] is required! - see example for options * @return self */ public function addType($name, array $options) { if (!isset($options['time']) || !isset($options['text'])) { trigger_error('addType requires $options["time"] and $options["text"]', E_USER_ERROR); } if (isset($this->types[$name])) { trigger_error('$this->types already have a ' . $name . ', please use a unique identifier', E_USER_ERROR); } $this->types[$name] = $options; return $this; } /** * Method to remove a type from {@link types} using the name * @example example.php 0 38 * @param string $name * @return bool */ public function removeType($name) { if (isset($this->types[$name])) { unset($this->types[$name]); return true; } return false; } /** * Method to add timers to the conversion * @example example.php 38 111 * @param timestamp $endtime timestamp of the endtime * @param timestamp $starttime timestamp of the starttime ( null = time() ) * @param mixed $id a unique identifier if you convert many at one time * @return self */ public function addTimer($endtime, $starttime = null, $id = null) { if ($endtime > ($starttime === null ? time() : $starttime)) { trigger_error('endtime can not be higher than startime - NOT IMPLEMENTED YET', E_USER_ERROR); } // How long time is there between our dates in seconds? $array = array('starttimer' => ($starttime === null ? time() : $starttime), 'endtimer' => $endtime, 'timer' => $endtime - ($starttime === null ? time() : $starttime)); if ($id !== null) $this->timer[$id] = $array; else $this->timer[] = $array; return $this; } /** * Method to remove one or all timers * @example example.php 111 * @param string $id a unique identifier if you want to remove only one * @return int numbers of deleted timers */ public function removeTimer($id = null) { if ($id === null) { $count = count($this->timer); $this->timer = array(); return $count; } if (isset($this->timer[$id])) { unset($this->timer[$id]); return 1; } else { return 0; } } /** * Method which returns a array of needles found in haystack * @param string $haystack * @param string $needle * @param integer $offset * @return array */ protected static function strallpos($haystack,$needle,$offset = 0) { $result = array(); for($i = $offset; $i<strlen($haystack); $i++){ $pos = strpos($haystack,$needle,$i); if($pos !== FALSE){ $offset = $pos; if($offset >= $i){ $i = $offset; $result[] = $offset; } } } return $result; } /** * Our main method which convert our {@link timer} using {@link types} to get our conversion * @param string $timerId * @param string $name * @return array * @access protected */ protected function getUnit($timerId, $name) { $options = $this->types[$name]; $timer = $this->timer[$timerId]; $timestring = ($timer['timer'] == 0 ? 0 : $timer['timer']/$options['time']); $assignments = (isset($options['assign']) ? count($options['assign']) : 0); $questionmarks = count(self::strallpos($options['text'], $this->textAssigner)); if ($questionmarks > $assignments) { trigger_error('There are more ' . $this->textAssigner . ' (' . $questionmarks . ') in the text than in the assignments (' . $assignments. ')', E_USER_NOTICE); } if ($questionmarks < $assignments) { trigger_error('There are less ' . $this->textAssigner . ' (' . $questionmarks . ') in the text than in the assignments (' . $assignments. ')', E_USER_NOTICE); } if ($assignments) { $assignments = array(); foreach ($options['assign'] AS $assign) { if (is_array($assign)) { list($sep, $num, $true, $false) = $assign; /** * @todo get rid of the switch! * $assignments[] = ($timer $sep $num ? $true : $false); * would be the best! */ switch ($sep) { case self::LESS_THAN: $assignments[] = (floor($timestring) < (int)$num ? $true : $false); break; case self::HIGHER_THAN: $assignments[] = (floor($timestring) > (int)$num ? $true : $false); break; case self::EQUALS: $assignments[] = (floor($timestring) == (int)$num ? $true : $false); break; } } else { $assignments[] = str_replace($this->textReplacer, floor($timestring), $assign); } } $options['timestring'] = array('floored' => floor($timestring), 'normal' => $timestring); $options['assignments'] = $assignments; $options['text'] = ($this->textAssigner != '%s' ? str_replace($this->textAssigner, '%s', $options['text']) : $options['text']); $text = call_user_func_array('sprintf', array_merge((array)$options['text'], $assignments)); } else { $text = $options['text']; } return array('converter' => array($name => $options), 'translated' => $text); } /** * Just a method to sort our array * @param array $a * @param array $b * @return int */ static protected function sorttypes($a, $b) { if ($a['time'] == $b['time']) return 0; return ($a['time'] > $b['time']) ? -1 : 1; } /** * To get our results, and only get the results. * If more than one {@link timer} this will return array otherwise just a string * @example example.php 38 111 * @return string/array */ public function __toString() { $results = $this->getResult(); $returns = array(); $count = count($this->timer); foreach($this->timer AS $id => $timer) { if ($count == 1) return $timer['result']['translated']; else $returns[$id] = $timer['result']['translated']; } $this->removeTimer(); return $returns; } /** * @link __toString()} * @return string/array */ public function toString() { return $this->__toString(); } /** * To get our results, with all information about the conversion tool used. * @example example.php 38 111 * @return array */ public function getResult() { // Lets start by sorting the types array uasort($this->types, array(self, 'sorttypes')); // Which should we use? foreach ($this->timer AS $timerid => $timer) { $last = null; $firstrun = true; foreach ($this->types AS $name => $options) { // If the time in the types are bigger than the timer, we dont want that, // but we will store the name in the $last if ($timer['timer'] < 0 && $options['time'] > 0) continue; if ($firstrun === true && ($options['time'] <= $timer['timer'])) { $this->timer[$timerid]['result'] = $this->getUnit($timerid, $name); break; } if ($options['time'] >= $timer['timer']) { $firstrun = false; $last = $name; continue; } // Aha, here the timer is larger than types timer, so we will pick the last one found // But if we havent found a $last, we will get the name from the loop $this->timer[$timerid]['result'] = $this->getUnit($timerid, ($last === null ? $name : $last) ); } if (! $this->timer[$timerid]['result']) { // Here the timer is larger than all the types timer, so we will use the last found $this->timer[$timerid]['result'] = $this->getUnit($timerid, $last); } } return $this->timer; } }