vlibDate.php 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2002 Active Fish Group |
  7. // +----------------------------------------------------------------------+
  8. // | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk> |
  9. // +----------------------------------------------------------------------+
  10. //
  11. // $Id: vlibDate.php 1438 2006-10-29 13:26:42Z b4rt $
  12. // check to avoid multiple including of class
  13. if (!defined('vlibDateClassLoaded')) {
  14. define('vlibDateClassLoaded', 1);
  15. include_once(dirname(__FILE__).'/vlibDate/error.php');
  16. include_once (dirname(__FILE__).'/vlibIni.php');
  17. /**
  18. * vlibDate is a class for manipulating dates (not times).
  19. * There are 2 main uses for this class:
  20. *
  21. * 1) to handle dates outside of the normal date range of 32-bit systems.
  22. * this can be handy for handling Dates of Birth for example.
  23. *
  24. * 2) to easily handle dates in different languages.
  25. * vlibDate has several supported languages and the possibility to
  26. * handle as many as submitted, so if you would like a language
  27. * added, see the CONTRIBUTE section of the documentation.
  28. *
  29. * For more information see the vlibDate.html in the 'docs' directory.
  30. *
  31. * @since 03/04/2002
  32. * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
  33. * @package vLIB
  34. * @access public
  35. * @see vlibDate.html
  36. */
  37. class vlibDate {
  38. /*-----------------------------------------------------------------------------\
  39. | ATTENTION |
  40. | Do not touch the following variables. vlibDate will not work otherwise. |
  41. \-----------------------------------------------------------------------------*/
  42. /** contains the list of language specific weekdays */
  43. var $days = array();
  44. /** if abbreviations are not a substring of the weekday i.e. in Portuguese*/
  45. var $daysabbr = array();
  46. /** contains the list of language specific months */
  47. var $months = array();
  48. /** contains the list of suffixes */
  49. var $suffixes = array();
  50. /** a list of possible languages. */
  51. var $accepted_langs = array('en','fr','de','es','pt','nl','it','no','sv','da','fi','ro','ar','ru');
  52. /*-----------------------------------------------------------------------------\
  53. | public functions |
  54. \-----------------------------------------------------------------------------*/
  55. /** FUNCTION: formatDate
  56. *
  57. * Formats the date like strftime(), but can handle dates from year 0001 - 9999
  58. * and can display dates in different languages.
  59. *
  60. * formatting options:
  61. *
  62. * %a abbreviated weekday name according to the current language setting (Mon, Tue..)
  63. * %A full weekday name according to the current language setting (Sunday, Monday, Tuesday...)
  64. * %b abbreviated month name according to the current (Jan, Feb, Mar)
  65. * %B full month name according to the current (January, February, March)
  66. * %d day of the month as a decimal number (range 01 to 31)
  67. * %e day of the month as a decimal number (range 0 to 31)
  68. * %E number of days since unspecified epoch (integer)
  69. * (%E is useful for storing a date in a Db/Session ..etc as an integer value.
  70. * Then use daysToDate() to convert back to a date.)
  71. * %j day of the year as a decimal number (range 001 to 366)
  72. * %m month as decimal number (range 01 to 12)
  73. * %n newline character
  74. * %s ordinal suffix for day of month
  75. * %t tab character
  76. * %U week number of current year as a decimal number, starting with the first Sunday
  77. * as the first day of the first week.
  78. * %w weekday as decimal (0 = Sunday)
  79. * %y year as a decimal number without a century (range 00 to 99)
  80. * %Y year as a decimal number including the century (range 0000 to 9999)
  81. * %% literal '%'
  82. *
  83. * @param string $timestamp vlibDate timestamp
  84. * @param string $format for returned string
  85. * @return string date in $format
  86. * @access public
  87. */
  88. function formatDate ($timestamp, $format) {
  89. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  90. if (empty($year)) $year = $this->_dateNow("%Y");
  91. if (empty($month)) $month = $this->_dateNow("%m");
  92. if (empty($day)) $day = $this->_dateNow("%d");
  93. $output = "";
  94. for ($strpos = 0; $strpos < strlen($format); $strpos++)
  95. {
  96. $char = substr($format,$strpos,1);
  97. if ($char == "%")
  98. {
  99. $nextchar = substr($format,$strpos + 1,1);
  100. switch ($nextchar)
  101. {
  102. case "a":
  103. $output .= $this->getWeekdayAbbrname($timestamp);
  104. break;
  105. case "A":
  106. $output .= $this->getWeekdayFullname($timestamp);
  107. break;
  108. case "b":
  109. $output .= $this->getMonthAbbrname($timestamp);
  110. break;
  111. case "B":
  112. $output .= $this->getMonthFullname($timestamp);
  113. break;
  114. case "d":
  115. $output .= sprintf("%02d",$day);
  116. break;
  117. case "e":
  118. $output .= sprintf("%01d",$day);
  119. break;
  120. case "E":
  121. $output .= $this->dateToDays($timestamp);
  122. break;
  123. case "j":
  124. $output .= $this->julianDate($timestamp);
  125. break;
  126. case "m":
  127. $output .= sprintf("%02d",$month);
  128. break;
  129. case "n":
  130. $output .= "\n";
  131. break;
  132. case "s":
  133. $output .= $this->getSuffix($timestamp);
  134. break;
  135. case "t":
  136. $output .= "\t";
  137. break;
  138. case "U":
  139. $output .= $this->weekOfYear($timestamp);
  140. break;
  141. case "w":
  142. $output .= $this->dayOfWeek($timestamp);
  143. break;
  144. case "W":
  145. $output .= $this->weekOfYear($timestamp, true);
  146. break;
  147. case "y":
  148. $output .= substr($year,2,2);
  149. break;
  150. case "Y":
  151. $output .= $year;
  152. break;
  153. case "%":
  154. $output .= "%";
  155. break;
  156. default:
  157. $output .= $char.$nextchar;
  158. }
  159. $strpos++;
  160. }
  161. else {
  162. $output .= $char;
  163. }
  164. }
  165. return $output;
  166. }
  167. /** FUNCTION: getMonthFullname
  168. *
  169. * Returns the full month name for the vlibDate $timestamp.
  170. *
  171. * @param string $timestamp vlibDate timestamp
  172. * @return string full month name
  173. * @access public
  174. */
  175. function getMonthFullname ($timestamp) {
  176. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  177. if (empty($month)) $month = $this->_dateNow("%m");
  178. return $this->months[($month - 1)];
  179. }
  180. /** FUNCTION: getMonthAbbrname
  181. *
  182. * Returns the abbreviated month name for the vlibDate $timestamp.
  183. *
  184. * @param string $timestamp vlibDate timestamp
  185. * @param int length of abbreviation, default=3
  186. * @return string abbreviated month name
  187. * @access public
  188. */
  189. function getMonthAbbrname ($timestamp, $length=3) {
  190. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  191. if (empty($month)) $month = $this->_dateNow("%m");
  192. return substr($this->months[($month - 1)],0,$length);
  193. }
  194. /** FUNCTION: getWeekdayFullname
  195. *
  196. * Returns the full weekday name for the vlibDate $timestamp.
  197. *
  198. * @param string $timestamp vlibDate timestamp
  199. * @return string full weekday name
  200. * @access public
  201. */
  202. function getWeekdayFullname ($timestamp) {
  203. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  204. if (empty($year)) $year = $this->_dateNow("%Y");
  205. if (empty($month)) $month = $this->_dateNow("%m");
  206. if (empty($day)) $day = $this->_dateNow("%d");
  207. $weekday = $this->dayOfWeek("$year-$month-$day");
  208. return $this->days[$weekday];
  209. }
  210. /** FUNCTION: getWeekdayAbbrname
  211. *
  212. * Returns the abbreviated weekday name for the vlibDate $timestamp.
  213. *
  214. * @param string $timestamp vlibDate timestamp
  215. * @param int length of abbreviation, default=3
  216. * @return string abbreviated weekday name
  217. * @access public
  218. */
  219. function getWeekdayAbbrname ($timestamp, $length=3) {
  220. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  221. if (empty($year)) $year = $this->_dateNow("%Y");
  222. if (empty($month)) $month = $this->_dateNow("%m");
  223. if (empty($day)) $day = $this->_dateNow("%d");
  224. $weekday = $this->dayOfWeek("$year-$month-$day");
  225. if (!empty($this->daysabbr)) {
  226. return ($this->daysabbr[$weekday]);
  227. }
  228. else {
  229. return substr($this->days[$weekday],0,$length);
  230. }
  231. }
  232. /** FUNCTION: now
  233. *
  234. * returns a vlibDate timestamp for the current day.
  235. *
  236. * @return string vlibDate timestamp
  237. * @access public
  238. */
  239. function now () {
  240. return $this->_dateNow('%Y-%m-%d');
  241. }
  242. /** FUNCTION: getSuffix
  243. *
  244. * returns the suffix for the day of the month, i.e. 03 = rd (in english)
  245. *
  246. * @param string $timestamp vlibDate timestamp
  247. * @param string suffix
  248. * @access public
  249. */
  250. function getSuffix ($timestamp) {
  251. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  252. if (empty($day)) $day = $this->_dateNow("%e");
  253. return $this->suffixes[($day - 1)];
  254. }
  255. /** FUNCTION: mkTimestamp
  256. *
  257. * given the day, month and year of a date will return a vlibDate timestamp.
  258. *
  259. * @param string $year in YYYY format
  260. * @param string $month in MM format
  261. * @param string $day in DD format
  262. * @return string vlibDate timestamp
  263. * @access public
  264. */
  265. function mkTimestamp ($year="", $month="", $day="") {
  266. if(empty($year)) $year = $this->_dateNow("%Y");
  267. if(empty($month)) $month = $this->_dateNow("%m");
  268. if(empty($day)) $day = $this->_dateNow("%d");
  269. return "$year-$month-$day";
  270. }
  271. /** FUNCTION: fromUnixTime
  272. *
  273. * returns a vlibDate timestamp from a given unix timestamp.
  274. *
  275. * @param int $unixtime
  276. * @return string vlibDate timestamp
  277. * @access public
  278. */
  279. function fromUnixTime ($unixtime) {
  280. return strftime('%Y-%m-%d', $unixtime);
  281. }
  282. /** FUNCTION: setLang
  283. *
  284. * sets the current language to the language specified by $lang.
  285. * For a list of supported languages and there language codes, see
  286. * the vlibDate.html file in the 'docs' directory.
  287. *
  288. * @param string $lang language code of language.
  289. * @access public
  290. */
  291. function setLang ($lang='en') {
  292. if (in_array($lang, $this->accepted_langs)) {
  293. require (dirname(__FILE__).'/vlibDate/langrefs_'.$lang.'.php');
  294. $this->days = $days;
  295. $this->daysabbr = $daysabbr;
  296. $this->months = $months;
  297. $this->suffixes = $suffixes;
  298. }
  299. else { // raise error
  300. vlibDateError::raiseError('VD_ERROR_INVALID_LANG', FATAL);
  301. }
  302. }
  303. /** FUNCTION: addInterval
  304. *
  305. * this function adds a specified interval to the specified timestamp.
  306. * allowed intervals are DAY[S], WEEK[S], MONTH[S], YEAR[S]
  307. * and CENTURY [CENTURIES].
  308. * example of usage:
  309. * $date = new vlibDate ('en');
  310. * $now = $date->now();
  311. * $nextweek = $date->addInterval($now, '1 WEEK');
  312. * $nextweeknextyear = $date->addInterval($now, '1 WEEK 1 YEAR');
  313. *
  314. * you can use any combination of intervals.
  315. *
  316. * @param string $timestamp vlibDate timestamp
  317. * @param string $interval desired interval
  318. * @return string vlibDate timestamp
  319. * @access public
  320. */
  321. function addInterval ($timestamp, $interval) {
  322. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  323. // these vars hold the temporary values as we calculate
  324. $this->_day = $day;
  325. $this->_month = $month;
  326. $this->_year = $year;
  327. $this->_interval = 0;
  328. $this->_days = $this->dateToDays ($timestamp);
  329. preg_replace_callback( "/([\d]+)\s*([\w]+)/xS", function($m) {
  330. return $this->_calcAddInterval($m[1], $m[2]);
  331. },$interval);
  332. if ($this->_interval < 1) return $timestamp;
  333. $days = $this->_days + $this->_interval;
  334. return $this->daysToDate ($days);
  335. }
  336. /** FUNCTION: subInterval
  337. *
  338. * this function subtracts a specified interval from the specified timestamp.
  339. * allowed intervals are DAY[S], WEEK[S], MONTH[S], YEAR[S]
  340. * and CENTURY [CENTURIES].
  341. * example of usage:
  342. * $date = new vlibDate ('en');
  343. * $now = $date->now();
  344. * $lastweek = $date->subInterval($now, '1 WEEK');
  345. * $lastweeklastyear = $date->subInterval($now, '1 WEEK 1 YEAR');
  346. *
  347. * you can use any combination of intervals.
  348. *
  349. * @param string $timestamp vlibDate timestamp
  350. * @param string $interval desired interval
  351. * @return string vlibDate timestamp
  352. * @access public
  353. */
  354. function subInterval ($timestamp, $interval) {
  355. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  356. // these vars hold the temporary values as we calculate
  357. $this->_day = $day;
  358. $this->_month = $month;
  359. $this->_year = $year;
  360. $this->_interval = 0;
  361. $this->_days = $this->dateToDays ($timestamp);
  362. preg_replace_callback( "/([\d]+)\s*([\w]+)/xS", function($m) {
  363. return $this->_calcAddInterval($m[1],$m[2]);
  364. },$interval);
  365. if ($this->_interval < 1) return $timestamp;
  366. $days = $this->_days - $this->_interval;
  367. return $this->daysToDate ($days);
  368. }
  369. /** FUNCTION: nextDay
  370. *
  371. * Returns a vlibDate timestamp for the day after $timestamp.
  372. * If format is specified, then that format is returned instead
  373. * of the timestamp.
  374. *
  375. * @param string $timestamp vlibDate timestamp
  376. * @param string $format for returned date
  377. * @return string if date in given format or vlibDate timestamp
  378. * @access public
  379. */
  380. function nextDay ($timestamp, $format="%Y-%m-%d") {
  381. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  382. if (empty($year)) $year = $this->_dateNow("%Y");
  383. if (empty($month)) $month = $this->_dateNow("%m");
  384. if (empty($day)) $day = $this->_dateNow("%d");
  385. $days = $this->dateToDays("$year-$month-$day");
  386. return ($this->daysToDate($days + 1,$format));
  387. }
  388. /** FUNCTION: prevDay
  389. *
  390. * Returns a vlibDate timestamp for the day before $timestamp.
  391. * If format is specified, the that format is returned instead
  392. * of the timestamp.
  393. *
  394. * @param string $timestamp vlibDate timestamp
  395. * @param string $format for returned date
  396. * @return string if date in given format or vlibDate timestamp
  397. * @access public
  398. */
  399. function prevDay ($timestamp,$format="%Y-%m-%d") {
  400. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  401. if (empty($year)) $year = $this->_dateNow("%Y");
  402. if (empty($month)) $month = $this->_dateNow("%m");
  403. if (empty($day)) $day = $this->_dateNow("%d");
  404. $days = $this->dateToDays("$year-$month-$day");
  405. return ($this->daysToDate($days - 1,$format));
  406. }
  407. /** FUNCTION: isFutureDate
  408. *
  409. * Returns true if the timestamp is in the future.
  410. *
  411. * @param string $timestamp vlibDate timestamp
  412. * @return boolean true/false
  413. * @access public
  414. */
  415. function isFutureDate ($timestamp) {
  416. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  417. $this_year = $this->_dateNow("%Y");
  418. $this_month = $this->_dateNow("%m");
  419. $this_day = $this->_dateNow("%d");
  420. if ($year > $this_year) {
  421. return true;
  422. }
  423. elseif ($year == $this_year) {
  424. if ($month > $this_month) {
  425. return true;
  426. }
  427. elseif ($month == $this_month) {
  428. if ($day > $this_day) {
  429. return true;
  430. }
  431. }
  432. }
  433. return false;
  434. }
  435. /** FUNCTION: isPastDate
  436. *
  437. * Returns true if the timestamp is in the past.
  438. *
  439. * @param string $timestamp vlibDate timestamp
  440. * @return boolean true/false
  441. * @access public
  442. */
  443. function isPastDate ($timestamp) {
  444. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  445. $this_year = $this->_dateNow("%Y");
  446. $this_month = $this->_dateNow("%m");
  447. $this_day = $this->_dateNow("%d");
  448. if ($year < $this_year) {
  449. return true;
  450. }
  451. elseif ($year == $this_year) {
  452. if ($month < $this_month) {
  453. return true;
  454. }
  455. elseif ($month == $this_month) {
  456. if ($day < $this_day) {
  457. return true;
  458. }
  459. }
  460. }
  461. return false;
  462. }
  463. /** FUNCTION: isDate
  464. *
  465. * Returns true if the timestamp is valid, false otherwise.
  466. *
  467. * @param string $timestamp vlibDate timestamp
  468. * @return boolean true/false
  469. * @access public
  470. */
  471. function isDate ($timestamp) {
  472. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  473. if (empty($year) || empty($month) || empty($day)) return false;
  474. if ($year < 0 || $year > 9999) {
  475. return false;
  476. }
  477. if ($month < 1 || $month > 12) {
  478. return false;
  479. }
  480. if ($day < 1 || $day > $this->daysInMonth($month,$year)) {
  481. return false;
  482. }
  483. return true;
  484. }
  485. /** FUNCTION: isLeapYear
  486. *
  487. * Returns true if $year is a leap year.
  488. *
  489. * @param string $year in format YYYY or a vlibDate timestamp
  490. * @return boolean true/false
  491. * @access public
  492. */
  493. function isLeapYear ($year="") {
  494. if (strlen($year) > 4) { // timestamp has bee parsed
  495. list ($day, $month, $year) = array_values($this->_breakTimestamp($year));
  496. }
  497. elseif (strlen($year) == 2) {
  498. $year = $this->getLongYear($year);
  499. }
  500. elseif (empty($year)) {
  501. $year = $this->_dateNow("%Y");
  502. }
  503. if (preg_match("/\D/",$year)) return false;
  504. return (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
  505. }
  506. /** FUNCTION: dayOfWeek
  507. *
  508. * Returns day of week for the timestamp: 0=Sunday ... 6=Saturday
  509. *
  510. * @param string $timestamp vlibDate timestamp
  511. * @return int $weekday_number
  512. * @access public
  513. */
  514. function dayOfWeek ($timestamp) {
  515. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  516. if (empty($year)) $year = $this->_dateNow("%Y");
  517. if (empty($month)) $month = $this->_dateNow("%m");
  518. if (empty($day)) $day = $this->_dateNow("%d");
  519. if ($month > 2) {
  520. $month -= 2;
  521. }
  522. else {
  523. $month += 10;
  524. $year--;
  525. }
  526. $day = (floor((13 * $month - 1) / 5) +
  527. $day + ($year % 100) +
  528. floor(($year % 100) / 4) +
  529. floor(($year / 100) / 4) - 2 *
  530. floor($year / 100) + 77);
  531. $weekday_number = (($day - 7 * floor($day / 7)));
  532. return $weekday_number;
  533. }
  534. /** FUNCTION: weekOfYear
  535. *
  536. * Returns week of the year.
  537. * If $start_monday is true, then the first week of the Year starts with the first
  538. * Monday of the year, otherwise it's the first Sunday.
  539. *
  540. * @param string $timestamp vlibDate timestamp
  541. * @param bool $start_monday
  542. * @return integer $week_number
  543. * @access public
  544. */
  545. function weekOfYear ($timestamp, $start_monday=false) {
  546. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  547. if (empty($year)) $year = $this->_dateNow("%Y");
  548. if (empty($month)) $month = $this->_dateNow("%m");
  549. if (empty($day)) $day = $this->_dateNow("%d");
  550. $week_year = $year - 1501;
  551. $capt_days = ($start_monday) ? 29873 : 29872;
  552. $week_day = $week_year * 365 + floor($week_year / 4) - $capt_days + 1
  553. - floor($week_year / 100) + floor(($week_year - 300) / 400);
  554. $week_number = floor(($this->julianDate("$year-$month-$day") + floor(($week_day + 4) % 7)) / 7);
  555. return $week_number;
  556. }
  557. /** FUNCTION: julianDate
  558. *
  559. * Returns number of days since (and including) 1st January of the year
  560. * in the given timestamp.
  561. *
  562. * @param string $timestamp vlibDate timestamp
  563. * @return int $julian
  564. * @access public
  565. */
  566. function julianDate ($timestamp) {
  567. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  568. if (empty($year)) $year = $this->_dateNow("%Y");
  569. if (empty($month)) $month = $this->_dateNow("%m");
  570. if (empty($day)) $day = $this->_dateNow("%d");
  571. $days = array(0,31,59,90,120,151,181,212,243,273,304,334);
  572. $julian = ($days[$month - 1] + $day);
  573. if ($month > 2 && $this->isLeapYear($year)) $julian++;
  574. return ($julian);
  575. }
  576. /** FUNCTION: quarterOfYear
  577. *
  578. * Returns quarter of the year for given timestamp.
  579. *
  580. * @param string $timestamp vlibDate timestamp
  581. * @return int $year_quarter
  582. * @access public
  583. */
  584. function quarterOfYear ($timestamp) {
  585. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  586. if (empty($year)) $year = $this->_dateNow("%Y");
  587. if (empty($month)) $month = $this->_dateNow("%m");
  588. if (empty($day)) $day = $this->_dateNow("%d");
  589. $year_quarter = (intval(($month - 1) / 3 + 1));
  590. return $year_quarter;
  591. }
  592. /** FUNCTION: getLongYear
  593. *
  594. * Returns the year in YYYY format for the given year in YY format.
  595. * 0-49 is considered 21st century, 50-99 is 20th century.
  596. *
  597. * @param string $year in YY format
  598. * @return string year in YYYY format
  599. * @access public
  600. */
  601. function getLongYear ($year) {
  602. if (strlen($year) == 1) return ("200$year");
  603. if ($year > 50) {
  604. return ("19$year");
  605. }
  606. else {
  607. return ("20$year");
  608. }
  609. }
  610. /** FUNCTION: diffInDays
  611. *
  612. * Returns number of days between two given dates.
  613. *
  614. * @param string $timestamp1 vlibDate timestamp
  615. * @param string $timestamp2 vlibDate timestamp
  616. * @return int absolute number of days between dates, or false on error
  617. * @access public
  618. */
  619. function diffInDays ($timestamp1,$timestamp2) {
  620. if (!$this->isDate($timestamp1)) return false;
  621. if (!$this->isDate($timestamp2)) return false;
  622. return (abs(($this->dateToDays($timestamp1)) - ($this->dateToDays($timestamp2))));
  623. }
  624. /** FUNCTION: daysInMonth
  625. *
  626. * Find the number of days in the $month.
  627. *
  628. * @param mixed int month in MM format or a string vlibDate timestamp
  629. * @param string year in YYYY format
  630. * @return int number of days
  631. * @access public
  632. */
  633. function daysInMonth ($month="",$year="") {
  634. if (strlen($month) > 2) { // timestamp has bee parsed
  635. list ($day, $month, $year) = array_values($this->_breakTimestamp($month));
  636. }
  637. else {
  638. if (empty($year)) $year = $this->_dateNow("%Y");
  639. if (empty($month)) $month = $this->_dateNow("%m");
  640. }
  641. $months = array (31,28,31,30,31,30,31,31,30,31,30,31);
  642. $days = $months[($month-1)];
  643. return (($month == 2 && $this->isLeapYear($year)) ? ($days+1) : $days);
  644. }
  645. /** FUNCTION: dateToDays
  646. *
  647. * Converts a vlibDate timestamp to a number of days since a long
  648. * distant epoch.
  649. * You can use this to store dates or to pass dates from 1
  650. * URL to another.
  651. *
  652. * @param string $timestamp vlibDate timestamp
  653. * @return int number of days
  654. * @access public
  655. */
  656. function dateToDays ($timestamp) {
  657. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  658. $century = substr($year,0,2);
  659. $year = substr($year,2,2);
  660. if ($month > 2) {
  661. $month -= 3;
  662. }
  663. else {
  664. $month += 9;
  665. if ($year) {
  666. $year--;
  667. }
  668. else {
  669. $year = 99;
  670. $century --;
  671. }
  672. }
  673. return ( floor(( 146097 * $century) / 4 ) +
  674. floor(( 1461 * $year) / 4 ) +
  675. floor(( 153 * $month + 2) / 5 ) +
  676. $day + 1721119);
  677. }
  678. /** FUNCTION: encodeDate
  679. *
  680. * alias for dateToDays().
  681. *
  682. */
  683. function encodeDate ($timestamp) {
  684. return $this->dateToDays($timestamp);
  685. }
  686. /** FUNCTION: daysToDate
  687. *
  688. * Converts a number of days since a long distant epoch
  689. * to a vlibDate timestamp or to a format specified by $format.
  690. *
  691. * @param int $days days since long distant epoch
  692. * @return string vlibDate timestamp or other $format
  693. * @access public
  694. */
  695. function daysToDate ($days,$format="%Y-%m-%d")
  696. {
  697. $days -= 1721119;
  698. $century = floor(( 4 * $days - 1) / 146097);
  699. $days = floor(4 * $days - 1 - 146097 * $century);
  700. $day = floor($days / 4);
  701. $year = floor(( 4 * $day + 3) / 1461);
  702. $day = floor(4 * $day + 3 - 1461 * $year);
  703. $day = floor(($day + 4) / 4);
  704. $month = floor(( 5 * $day - 3) / 153);
  705. $day = floor(5 * $day - 3 - 153 * $month);
  706. $day = floor(($day + 5) / 5);
  707. if ($month < 10) {
  708. $month +=3;
  709. }
  710. else {
  711. $month -=9;
  712. if ($year++ == 99) {
  713. $year = 0;
  714. $century++;
  715. }
  716. }
  717. $century = sprintf("%02d",$century);
  718. $year = sprintf("%02d",$year);
  719. $month = sprintf("%02d",$month);
  720. $day = sprintf("%02d",$day);
  721. return ($this->formatDate("$century$year-$month-$day",$format));
  722. }
  723. /** FUNCTION: decodeDate
  724. *
  725. * alias for daysToDate().
  726. *
  727. */
  728. function decodeDate ($days, $format="%Y-%m-%d") {
  729. return $this->daysToDate($days, $format);
  730. }
  731. /** FUNCTION: getYear
  732. *
  733. * Returns the current year in YYYY format
  734. *
  735. * @return string year in YYYY format
  736. * @access public
  737. */
  738. function getYear () {
  739. return $this->_dateNow("%Y");
  740. }
  741. /** FUNCTION: getMonth
  742. *
  743. * Returns the current month in MM format
  744. *
  745. * @return string month in MM format
  746. * @access public
  747. */
  748. function getMonth () {
  749. return $this->_dateNow("%m");
  750. }
  751. /** FUNCTION: getDay
  752. *
  753. * Returns the current day in DD format
  754. *
  755. * @return string day in DD format
  756. * @access public
  757. */
  758. function getDay () {
  759. return $this->_dateNow("%d");
  760. }
  761. /*-----------------------------------------------------------------------------\
  762. | private functions |
  763. \-----------------------------------------------------------------------------*/
  764. /** FUNCTION: _calcSubInterval
  765. *
  766. * does the calculations for $this->subInterval();
  767. *
  768. * @param int $number number of $interval's
  769. * @param string $interval type of interval, i.e. DAY, MONTH ...etc.
  770. * @access private
  771. */
  772. function _calcSubInterval ($number, $interval) {
  773. $interval = strtoupper($interval);
  774. if (substr($interval, -1, 1)=='S') $interval = substr($interval, 0, -1);
  775. /* retreive the timestamp with the interval added so we can keep track
  776. of the current year and month of calculation */
  777. $timestamp = $this->daysToDate (($this->_days - $this->_interval));
  778. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  779. switch ($interval) {
  780. case 'DAY':
  781. if ($number > 0) {
  782. $this->_interval += $number;
  783. }
  784. break;
  785. case 'WEEK':
  786. if ($number > 0) {
  787. $this->_interval += ($number*7);
  788. }
  789. break;
  790. case 'MONTH':
  791. if ($number > 0) {
  792. for ($i=0; $i < $number; $i++) {
  793. // first we goto prev month
  794. if ($month != 1) {
  795. $month--;
  796. }
  797. else {
  798. $month = 12;
  799. $year--;
  800. }
  801. $sub = $this->daysInMonth($month, $year);
  802. $this->_interval += $sub;
  803. }
  804. }
  805. break;
  806. case 'CENTURIE':
  807. $interval = 'CENTURY';
  808. case 'CENTURY':
  809. $interval = 'YEAR';
  810. $number *= 100;
  811. case 'YEAR':
  812. if ($number > 0) {
  813. for ($i=0; $i < $number; $i++) {
  814. if (
  815. ($month < 3 && $this->isLeapYear(($year-1))) or
  816. ($month > 2 && $this->isLeapYear($year))
  817. ) {
  818. $this->_interval += 366;
  819. }
  820. else {
  821. $this->_interval += 365;
  822. }
  823. $year--; // goto previous year
  824. }
  825. }
  826. break;
  827. }
  828. return;
  829. }
  830. /** FUNCTION: _calcAddInterval
  831. *
  832. * does the calculations for $this->addInterval();
  833. *
  834. * @param int $number number of $interval's
  835. * @param string $interval type of interval, i.e. DAY, MONTH ...etc.
  836. * @access private
  837. */
  838. function _calcAddInterval ($number, $interval) {
  839. $interval = strtoupper($interval);
  840. if (substr($interval, -1, 1)=='S') $interval = substr($interval, 0, -1);
  841. /* retreive the timestamp with the interval added so we can keep track
  842. of the current year and month of calculation */
  843. $timestamp = $this->daysToDate (($this->_days + $this->_interval));
  844. list ($day, $month, $year) = array_values($this->_breakTimestamp($timestamp));
  845. switch ($interval) {
  846. case 'DAY':
  847. if ($number > 0) {
  848. $this->_interval += $number;
  849. }
  850. break;
  851. case 'WEEK':
  852. if ($number > 0) {
  853. $this->_interval += ($number*7);
  854. }
  855. break;
  856. case 'MONTH':
  857. if ($number > 0) {
  858. for ($i=0; $i < $number; $i++) {
  859. $add = $this->daysInMonth($month, $year);
  860. $this->_interval += $add;
  861. if ($month < 12) {
  862. $month++;
  863. }
  864. else {
  865. $month = 1;
  866. $year++;
  867. }
  868. }
  869. }
  870. break;
  871. case 'CENTURIE':
  872. $interval = 'CENTURY';
  873. case 'CENTURY':
  874. $interval = 'YEAR';
  875. $number *= 100;
  876. case 'YEAR':
  877. if ($number > 0) {
  878. for ($i=0; $i < $number; $i++) {
  879. if (
  880. ($month < 3 && $this->isLeapYear($year)) or
  881. ($month > 2 && $this->isLeapYear(($year+1)))
  882. ) {
  883. $this->_interval += 366;
  884. }
  885. else {
  886. $this->_interval += 365;
  887. }
  888. $year++;
  889. }
  890. }
  891. break;
  892. }
  893. return;
  894. }
  895. /** FUNCTION: vlibDate [constructor]
  896. *
  897. * This function includes the languages specfic variables for displaying
  898. * weekdays and months for example.
  899. *
  900. * @param string $lang language, see documentation for a list of langs.
  901. * @access public
  902. */
  903. function vlibDate ($lang = null) {
  904. $config = vlibIni::vlibDate();
  905. $default_lang = $config['DEFAULT_LANG'];
  906. $this->setLang((($lang != null) ? $lang : $default_lang));
  907. }
  908. /**
  909. * Returns the current local date. NOTE: This function
  910. * retrieves the local date using strftime(), which may
  911. * or may not be 32-bit safe on your system.
  912. *
  913. * @param string the strftime() format to return the date
  914. * @access private
  915. * @return string the current date in specified format
  916. */
  917. function _dateNow($format="%Y%m%d") {
  918. return(strftime($format,time()));
  919. }
  920. /**
  921. * Returns an array with day, month, year key values for a timstamp.
  922. *
  923. * @param string $timestamp
  924. * @access private
  925. * @return array associative array with date values.
  926. */
  927. function _breakTimestamp ($timestamp) {
  928. $timestamp = preg_replace("/[\D]/", '', $timestamp); // remove all non digits
  929. if (strlen($timestamp) == 8) {
  930. $year = substr($timestamp, 0, 4);
  931. $month= substr($timestamp, 4, 2);
  932. $day = substr($timestamp, 6, 2);
  933. return array('day'=>$day, 'month'=>$month, 'year'=>$year);
  934. }
  935. else {
  936. vlibDateError::raiseError('VD_ERROR_INVALID_TIMESTAMP', FATAL);
  937. }
  938. }
  939. } // end class vlibDate
  940. } // << end if(!defined())..
  941. ?>