2 // +----------------------------------------------------------------------+
 
   3 // | Anuko Time Tracker
 
   4 // +----------------------------------------------------------------------+
 
   5 // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
 
   6 // +----------------------------------------------------------------------+
 
   7 // | LIBERAL FREEWARE LICENSE: This source code document may be used
 
   8 // | by anyone for any purpose, and freely redistributed alone or in
 
   9 // | combination with other software, provided that the license is obeyed.
 
  11 // | There are only two ways to violate the license:
 
  13 // | 1. To redistribute this code in source form, with the copyright
 
  14 // |    notice or license removed or altered. (Distributing in compiled
 
  15 // |    forms without embedded copyright notices is permitted).
 
  17 // | 2. To redistribute modified versions of this code in *any* form
 
  18 // |    that bears insufficient indications that the modifications are
 
  19 // |    not the work of the original author(s).
 
  21 // | This license applies to this document only, not any other software
 
  22 // | that it may be combined with.
 
  24 // +----------------------------------------------------------------------+
 
  26 // | https://www.anuko.com/time_tracker/credits.htm
 
  27 // +----------------------------------------------------------------------+
 
  30  * Parse a time/date generated with strftime().
 
  32  * This function is the same as the original one defined by PHP (Linux/Unix only),
 
  33  *  but now you can use it on Windows too.
 
  34  *  Limitation : Only this format can be parsed %S, %M, %H, %d, %m, %Y
 
  36  * @author Lionel SAURON
 
  40  * @param $sDate(string)    The string to parse (e.g. returned from strftime()).
 
  41  * @param $sFormat(string)  The format used in date  (e.g. the same as used in strftime()).
 
  42  * @return (array)          Returns an array with the <code>$sDate</code> parsed, or <code>false</code> on error.
 
  45 function my_strptime($sDate, $sFormat)
 
  62         // ===== Search a %x element, Check the static string before the %x =====
 
  63         $nIdxFound = strpos($sFormat, '%');
 
  64         if($nIdxFound === false)
 
  67             // There is no more format. Check the last static string.
 
  68             $aResult['unparsed'] = ($sFormat == $sDate) ? "" : $sDate;
 
  72         $sFormatBefore = mb_substr($sFormat, 0, $nIdxFound);
 
  73         $sDateBefore   = mb_substr($sDate,   0, $nIdxFound);
 
  75         if($sFormatBefore != $sDateBefore) break;
 
  77         // ===== Read the value of the %x found =====
 
  78         $sFormat = mb_substr($sFormat, $nIdxFound);
 
  79         $sDate   = mb_substr($sDate,   $nIdxFound);
 
  81         $aResult['unparsed'] = $sDate;
 
  83         $sFormatCurrent = mb_substr($sFormat, 0, 2);
 
  84         $sFormatAfter   = mb_substr($sFormat, 2);
 
  88         switch($sFormatCurrent)
 
  90             case '%S': // Seconds after the minute (0-59)
 
  92                 sscanf($sDate, "%2d%[^\\n]", $nValue, $sDateAfter);
 
  94                 if(($nValue < 0) || ($nValue > 59)) return false;
 
  96                 $aResult['tm_sec']  = $nValue;
 
 100             case '%M': // Minutes after the hour (0-59)
 
 101                 sscanf($sDate, "%2d%[^\\n]", $nValue, $sDateAfter);
 
 103                 if(($nValue < 0) || ($nValue > 59)) return false;
 
 105                 $aResult['tm_min']  = $nValue;
 
 109             case '%H': // Hour since midnight (0-23)
 
 110                 sscanf($sDate, "%2d%[^\\n]", $nValue, $sDateAfter);
 
 112                 if(($nValue < 0) || ($nValue > 23)) return false;
 
 114                 $aResult['tm_hour']  = $nValue;
 
 118             case '%d': // Day of the month (1-31)
 
 119                 sscanf($sDate, "%2d%[^\\n]", $nValue, $sDateAfter);
 
 121                 if(($nValue < 1) || ($nValue > 31)) return false;
 
 123                 $aResult['tm_mday']  = $nValue;
 
 127             case '%m': // Months since January (0-11)
 
 128                 sscanf($sDate, "%2d%[^\\n]", $nValue, $sDateAfter);
 
 130                 if(($nValue < 1) || ($nValue > 12)) return false;
 
 132                 $aResult['tm_mon']  = ($nValue - 1);
 
 136             case '%Y': // Years since 1900
 
 137                 sscanf($sDate, "%4d%[^\\n]", $nValue, $sDateAfter);
 
 139                 if($nValue < 1900) return false;
 
 141                 $aResult['tm_year']  = ($nValue - 1900);
 
 146               //sscanf($sDate, "%s%[^\\n]", $skip, $sDateAfter);
 
 147               preg_match('/^(.+)(\s|$)/uU', $sDate, $matches);
 
 148               if (isset($matches[1])) {
 
 149                 $sDateAfter = mb_substr($sDate, mb_strlen($matches[1]));
 
 153               //break 2; // Break Switch and while
 
 157         // ===== Next please =====
 
 158         $sFormat = $sFormatAfter;
 
 159         $sDate   = $sDateAfter;
 
 161         $aResult['unparsed'] = $sDate;
 
 163     } // END while($sFormat != "")
 
 166     // ===== Create the other value of the result array =====
 
 167     $nParsedDateTimestamp = mktime($aResult['tm_hour'], $aResult['tm_min'], $aResult['tm_sec'],
 
 168                             $aResult['tm_mon'] + 1, $aResult['tm_mday'], $aResult['tm_year'] + 1900);
 
 170     // Before PHP 5.1 return -1 when error
 
 171     if(($nParsedDateTimestamp === false)
 
 172     ||($nParsedDateTimestamp === -1)) return false;
 
 174     $aResult['tm_wday'] = (int) strftime("%w", $nParsedDateTimestamp); // Days since Sunday (0-6)
 
 175     $aResult['tm_yday'] = (strftime("%j", $nParsedDateTimestamp) - 1); // Days since January 1 (0-365)
 
 185   var $mDay;            // day of week
 
 186   var $mDate;           // day of month
 
 188   var $mIntrFormat      = "%d.%m.%Y %H:%M:%S"; //29.02.2004 16:21:42 internal format date
 
 190   var $mParseResult = 0;
 
 191   var $mAutoComplete = true;
 
 196    * @param String $format
 
 197    * @param String $strfDateTime
 
 198    * @return DateAndTime
 
 200   function DateAndTime($format="",$strfDateTime="") {
 
 201     $this->mLocalFormat = ($format ? $format : $this->mIntrFormat);
 
 202     $d = ($strfDateTime ? $strfDateTime : $this->do_strftime($this->mLocalFormat));
 
 206   function setFormat($format) {
 
 207     $this->mLocalFormat = $format;
 
 210   function getFormat() {
 
 211     return $this->mLocalFormat;
 
 215   function getDate() { return $this->mDate; }
 
 217   //0 (for Sunday) through 6 (for Saturday)
 
 218   function getDay() { return $this->mDay; }
 
 221   function getMonth() { return $this->mMonth; }
 
 224   function getYear() { return $this->mYear; }
 
 226   function setDate($value) { $this->mDate = $value; }
 
 227   function setMonth($value) { $this->mMonth = $value; }
 
 228   function setYear($value) { $this->mYear = $value; }
 
 230   function setTimestamp($ts) {
 
 231     $this->mDate = date("d",$ts);
 
 232     $this->mDay = date("w",$ts);
 
 233     $this->mMonth = date("m",$ts);
 
 234     $this->mYear = date("Y",$ts);
 
 235     $this->mHour = date("H",$ts);
 
 236     $this->mMinute = date("i",$ts);
 
 237     $this->mSecond = date("s",$ts);
 
 241    * Return UNIX timestamp
 
 243   function getTimestamp() {
 
 244     return @mktime($this->mHour, $this->mMinute, $this->mSecond, $this->mMonth, $this->mDate, $this->mYear);
 
 247   function compare($datetime) {
 
 248     $ts1 = $this->getTimestamp();
 
 249     $ts2 = $datetime->getTimestamp();
 
 250     if ($ts1<$ts2) return -1;
 
 251     if ($ts1==$ts2) return 0;
 
 252     if ($ts1>$ts2) return 1;
 
 255   function toString($format="") {
 
 256     if ($this->mParseResult==0) {
 
 258         return $this->do_strftime($format, $this->getTimestamp());
 
 260         return $this->do_strftime($this->mLocalFormat, $this->getTimestamp());
 
 264         return $this->do_strftime($format);
 
 266         return $this->do_strftime($this->mLocalFormat);
 
 271   function parseVal($szDate, $format="") {
 
 272     $useformat = ($format ? $format : $this->mLocalFormat);
 
 273     $res = my_strptime($szDate, $useformat);
 
 274     if ($res !== false) {
 
 275       $this->mDate = $res['tm_mday'];
 
 276       $this->mDay = $res['tm_wday'];
 
 277       $this->mMonth = $res['tm_mon'] + 1; // tm_mon - Months since January (0-11)
 
 278       $this->mYear = 1900 + $res['tm_year']; // tm_year - Years since 1900
 
 279       $this->mHour = $res['tm_hour'];
 
 280       $this->mMinute = $res['tm_min'];
 
 281       $this->mSecond = $res['tm_sec'];
 
 282       $this->mParseResult = 0;
 
 283     } elseif ($this->mAutoComplete) {
 
 284       $this->setTimestamp(time());
 
 285       $this->mParseResult = 1;
 
 290     if ($this->mParseResult!=0) return true;
 
 294   function getClone() {
 
 295     if (version_compare(phpversion(), '5.0') < 0) {
 
 296                 $d = new DateAndTime($this->getFormat());
 
 297                 $d->setTimestamp($this->getTimestamp());
 
 304   function before(/*DateAndTime*/ $obj) {
 
 305     if ($this->getTimestamp()<$obj->getTimestamp()) return true;
 
 309   function after(/*DateAndTime*/ $obj) {
 
 310     if ($this->getTimestamp()>$obj->getTimestamp()) return true;
 
 314   function equals(/*DateAndTime*/ $obj) {
 
 315     if ($this->getTimestamp() == $obj->getTimestamp()) return true;
 
 319   function nextDate() {
 
 320     $d = $this->getClone();
 
 325   function decDay(/*int*/$days=1) {
 
 326     $this->setTimestamp(@mktime($this->mHour, $this->mMinute, $this->mSecond, $this->mMonth, $this->mDate - $days, $this->mYear));
 
 329   function incDay(/*int*/$days=1) {
 
 330     $this->setTimestamp(@mktime($this->mHour, $this->mMinute, $this->mSecond, $this->mMonth, $this->mDate + $days, $this->mYear));
 
 334    * @param $format string Datetime format string
 
 335    * @return string Preprocessed string with all locale-depended format
 
 336    *                characters replaced by localized i18n strings.
 
 338   function preprocessFormatString($format) {
 
 340     if (isset($GLOBALS['i18n'])) {
 
 341       // replace locale-dependent strings
 
 342       $format = str_replace('%a', mb_substr($i18n->getWeekDayName($this->mDay), 0, 3, 'utf-8'), $format);
 
 343       $format = str_replace('%A', $i18n->getWeekDayName($this->mDay), $format);
 
 344       $abbrev_month = mb_substr($i18n->monthNames[$this->mMonth], 0, 3, 'utf-8');
 
 345       $format = str_replace('%b', $abbrev_month, $format);
 
 346       $format = str_replace('%h', $abbrev_month, $format);
 
 347       $format = str_replace('%z', date('O'), $format);
 
 348       $format = str_replace('%Z', date('O'), $format); // format as 'O' for consistency with JS strftime
 
 349       if (strpos($format, '%c') !== false) {
 
 350         $format = str_replace('%c', $this->preprocessFormatString('%a %d %b %Y %T %Z'), $format);
 
 356   function do_strftime($format, $timestamp = null)
 
 358     if (!is_null($timestamp)) {
 
 359       return strftime($this->preprocessFormatString($format), $timestamp);
 
 361       return strftime($this->preprocessFormatString($format));