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 __construct($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 before(/*DateAndTime*/ $obj) {
295 if ($this->getTimestamp() < $obj->getTimestamp()) return true;
299 function after(/*DateAndTime*/ $obj) {
300 if ($this->getTimestamp() > $obj->getTimestamp()) return true;
304 function equals(/*DateAndTime*/ $obj) {
305 if ($this->getTimestamp() == $obj->getTimestamp()) return true;
309 function decDay(/*int*/$days=1) {
310 $this->setTimestamp(@mktime($this->mHour, $this->mMinute, $this->mSecond, $this->mMonth, $this->mDate - $days, $this->mYear));
313 function incDay(/*int*/$days=1) {
314 $this->setTimestamp(@mktime($this->mHour, $this->mMinute, $this->mSecond, $this->mMonth, $this->mDate + $days, $this->mYear));
318 * @param $format string Datetime format string
319 * @return string Preprocessed string with all locale-depended format
320 * characters replaced by localized i18n strings.
322 function preprocessFormatString($format) {
325 // replace locale-dependent strings
326 $format = str_replace('%a', mb_substr($i18n->getWeekDayName($this->mDay), 0, 3, 'utf-8'), $format);
327 $format = str_replace('%A', $i18n->getWeekDayName($this->mDay), $format);
328 $abbrev_month = mb_substr($i18n->monthNames[$this->mMonth], 0, 3, 'utf-8');
329 $format = str_replace('%b', $abbrev_month, $format);
330 $format = str_replace('%h', $abbrev_month, $format);
331 $format = str_replace('%z', date('O'), $format);
332 $format = str_replace('%Z', date('O'), $format); // format as 'O' for consistency with JS strftime
333 if (strpos($format, '%c') !== false) {
334 $format = str_replace('%c', $this->preprocessFormatString('%a %d %b %Y %T %Z'), $format);
339 function do_strftime($format, $timestamp = null)
341 if (!is_null($timestamp)) {
342 return strftime($this->preprocessFormatString($format), $timestamp);
344 return strftime($this->preprocessFormatString($format));