date.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <?php
  2. /**
  3. * date.php
  4. *
  5. * Takes a date and parses it into a usable format. The form that a
  6. * date SHOULD arrive in is:
  7. * <Tue,> 29 Jun 1999 09:52:11 -0500 (EDT)
  8. * (as specified in RFC 822) -- 'Tue' is optional
  9. *
  10. * @copyright &copy; 1999-2006 The SquirrelMail Project Team
  11. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  12. * @version $Id$
  13. * @package squirrelmail
  14. * @subpackage date
  15. */
  16. /** Load up some useful constants */
  17. require_once(SM_PATH . 'functions/constants.php');
  18. /**
  19. * Corrects a time stamp to be the local time.
  20. *
  21. * @param int stamp the timestamp to adjust
  22. * @param string tzc the timezone correction
  23. * @return int the corrected timestamp
  24. */
  25. function getGMTSeconds($stamp, $tzc) {
  26. /* date couldn't be parsed */
  27. if ($stamp == -1) {
  28. return -1;
  29. }
  30. /* timezone correction, expressed as `shhmm' */
  31. switch($tzc)
  32. {
  33. case 'Pacific':
  34. case 'PST':
  35. $tzc = '-0800';
  36. break;
  37. case 'Mountain':
  38. case 'MST':
  39. case 'PDT':
  40. $tzc = '-0700';
  41. break;
  42. case 'Central':
  43. case 'CST':
  44. case 'MDT':
  45. $tzc = '-0600';
  46. break;
  47. case 'Eastern':
  48. case 'EST':
  49. case 'CDT':
  50. $tzc = '-0500';
  51. break;
  52. case 'EDT':
  53. $tzc = '-0400';
  54. break;
  55. case 'GMT':
  56. $tzc = '+0000';
  57. break;
  58. case 'BST':
  59. case 'MET':
  60. case 'CET':
  61. $tzc = '+0100';
  62. break;
  63. case 'EET':
  64. case 'IST':
  65. case 'MET DST':
  66. case 'METDST':
  67. $tzc = '+0200';
  68. break;
  69. case 'HKT':
  70. $tzc = '+0800';
  71. break;
  72. case 'JST':
  73. case 'KST':
  74. $tzc = '+0900';
  75. break;
  76. }
  77. $neg = false;
  78. if (substr($tzc, 0, 1) == '-') {
  79. $neg = true;
  80. } else if (substr($tzc, 0, 1) != '+') {
  81. $tzc = '+'.$tzc;
  82. }
  83. $hh = substr($tzc,1,2);
  84. $mm = substr($tzc,3,2);
  85. $iTzc = ($hh * 60 + $mm) * 60;
  86. if ($neg) $iTzc = -1 * (int) $iTzc;
  87. /* stamp in gmt */
  88. $stamp -= $iTzc;
  89. /* now find what the server is at */
  90. $current = date('Z', time());
  91. /* stamp in local timezone */
  92. $stamp += $current;
  93. return $stamp;
  94. }
  95. /**
  96. * Returns the (localized) string for a given day number.
  97. * Switch system has been intentionaly chosen for the
  98. * internationalization of month and day names. The reason
  99. * is to make sure that _("") strings will go into the
  100. * main po.
  101. *
  102. * @param int day_number the day number
  103. * @return string the day in human readable form
  104. */
  105. function getDayName( $day_number ) {
  106. switch( $day_number ) {
  107. case 0:
  108. $ret = _("Sunday");
  109. break;
  110. case 1:
  111. $ret = _("Monday");
  112. break;
  113. case 2:
  114. $ret = _("Tuesday");
  115. break;
  116. case 3:
  117. $ret = _("Wednesday");
  118. break;
  119. case 4:
  120. $ret = _("Thursday");
  121. break;
  122. case 5:
  123. $ret = _("Friday");
  124. break;
  125. case 6:
  126. $ret = _("Saturday");
  127. break;
  128. default:
  129. $ret = '';
  130. }
  131. return( $ret );
  132. }
  133. /**
  134. * Like getDayName, but returns the short form
  135. * @param int day_number the day number
  136. * @return string the day in short human readable form
  137. */
  138. function getDayAbrv( $day_number ) {
  139. switch( $day_number ) {
  140. case 0:
  141. $ret = _("Sun");
  142. break;
  143. case 1:
  144. $ret = _("Mon");
  145. break;
  146. case 2:
  147. $ret = _("Tue");
  148. break;
  149. case 3:
  150. $ret = _("Wed");
  151. break;
  152. case 4:
  153. $ret = _("Thu");
  154. break;
  155. case 5:
  156. $ret = _("Fri");
  157. break;
  158. case 6:
  159. $ret = _("Sat");
  160. break;
  161. default:
  162. $ret = '';
  163. }
  164. return( $ret );
  165. }
  166. /**
  167. * Returns the (localized) string for a given month number.
  168. *
  169. * @param string month_number the month number (01..12)
  170. * @return string the month name in human readable form
  171. */
  172. function getMonthName( $month_number ) {
  173. switch( $month_number ) {
  174. case '01':
  175. $ret = _("January");
  176. break;
  177. case '02':
  178. $ret = _("February");
  179. break;
  180. case '03':
  181. $ret = _("March");
  182. break;
  183. case '04':
  184. $ret = _("April");
  185. break;
  186. case '05':
  187. $ret = _("May");
  188. break;
  189. case '06':
  190. $ret = _("June");
  191. break;
  192. case '07':
  193. $ret = _("July");
  194. break;
  195. case '08':
  196. $ret = _("August");
  197. break;
  198. case '09':
  199. $ret = _("September");
  200. break;
  201. case '10':
  202. $ret = _("October");
  203. break;
  204. case '11':
  205. $ret = _("November");
  206. break;
  207. case '12':
  208. $ret = _("December");
  209. break;
  210. default:
  211. $ret = '';
  212. }
  213. return( $ret );
  214. }
  215. /**
  216. * Returns the (localized) string for a given month number,
  217. * short representation.
  218. *
  219. * @param string month_number the month number (01..12)
  220. * @return string the shortened month in human readable form
  221. */
  222. function getMonthAbrv( $month_number ) {
  223. switch( $month_number ) {
  224. case '01':
  225. $ret = _("Jan");
  226. break;
  227. case '02':
  228. $ret = _("Feb");
  229. break;
  230. case '03':
  231. $ret = _("Mar");
  232. break;
  233. case '04':
  234. $ret = _("Apr");
  235. break;
  236. case '05':
  237. $ret = _("Ma&#121;");
  238. break;
  239. case '06':
  240. $ret = _("Jun");
  241. break;
  242. case '07':
  243. $ret = _("Jul");
  244. break;
  245. case '08':
  246. $ret = _("Aug");
  247. break;
  248. case '09':
  249. $ret = _("Sep");
  250. break;
  251. case '10':
  252. $ret = _("Oct");
  253. break;
  254. case '11':
  255. $ret = _("Nov");
  256. break;
  257. case '12':
  258. $ret = _("Dec");
  259. break;
  260. default:
  261. $ret = '';
  262. }
  263. return( $ret );
  264. }
  265. /**
  266. * Returns the localized representation of the date/time.
  267. *
  268. * @param string date_format The format for the date, like the input for the PHP date() function.
  269. * @param int stamp the timestamp to convert
  270. * @return string a full date representation
  271. */
  272. function date_intl( $date_format, $stamp ) {
  273. $ret = str_replace( array('D','F','l','M'), array('$1','$2','$3','$4'), $date_format );
  274. // to reduce the date calls we retrieve m and w in the same call
  275. $ret = date('w#m#'. $ret, $stamp );
  276. // extract day and month in order to replace later by intl day and month
  277. $aParts = explode('#',$ret);
  278. $ret = str_replace(array('$1','$4','$2','$3',), array(getDayAbrv($aParts[0]),
  279. getMonthAbrv($aParts[1]),
  280. getMonthName($aParts[1]),
  281. getDayName($aParts[0])),
  282. $aParts[2]);
  283. return( $ret );
  284. }
  285. /**
  286. * This returns a date of the format "Wed, Oct 29, 2003 9:52 am",
  287. * or the same in 24H format (depending on the user's settings),
  288. * and taking localization into accout.
  289. *
  290. * @param int stamp the timestamp
  291. * @return string the long date string
  292. */
  293. function getLongDateString( $stamp ) {
  294. global $hour_format;
  295. if ($stamp == -1) {
  296. return '';
  297. }
  298. if ( $hour_format == SMPREF_TIME_12HR ) {
  299. $date_format = _("D, F j, Y g:i a");
  300. } else {
  301. $date_format = _("D, F j, Y H:i");
  302. }
  303. return( date_intl( $date_format, $stamp ) );
  304. }
  305. /**
  306. * Returns a short representation of the date,
  307. * taking timezones and localization into account.
  308. * Depending on user's settings, this string can be
  309. * of the form: "14:23" or "Jun 14, 2003" depending
  310. * on whether the stamp is "today" or not.
  311. *
  312. * @param int stamp the timestamp
  313. * @return string the date string
  314. */
  315. function getDateString( $stamp ) {
  316. global $invert_time, $hour_format, $show_full_date;
  317. if ( $stamp == -1 ) {
  318. return '';
  319. }
  320. $now = time();
  321. $dateZ = date('Z', $now );
  322. // FIXME: isn't this obsolete and introduced as a terrible workaround
  323. // for bugs at other places which are fixed a long time ago?
  324. if ($invert_time) {
  325. $dateZ = - $dateZ;
  326. }
  327. // calculate when it was midnight and when it will be,
  328. // in order to display dates differently if they're 'today'
  329. $midnight = $now - ($now % 86400) - $dateZ;
  330. // this is to correct if after calculations midnight is more than
  331. // one whole day away.
  332. if ($now - $midnight > 86400) {
  333. $midnight += 86400;
  334. }
  335. $nextmid = $midnight + 86400;
  336. if (($show_full_date == 1) || ($nextmid < $stamp)) {
  337. $date_format = _("M j, Y");
  338. } else if ($midnight < $stamp) {
  339. /* Today */
  340. if ( $hour_format == SMPREF_TIME_12HR ) {
  341. $date_format = _("g:i a");
  342. } else {
  343. $date_format = _("H:i");
  344. }
  345. } else if ($midnight - 518400 < $stamp) {
  346. /* This week */
  347. if ( $hour_format == SMPREF_TIME_12HR ) {
  348. $date_format = _("D, g:i a");
  349. } else {
  350. $date_format = _("D, H:i");
  351. }
  352. } else {
  353. /* before this week */
  354. $date_format = _("M j, Y");
  355. }
  356. return( date_intl( $date_format, $stamp ) );
  357. }
  358. /**
  359. * Decodes a RFC 822 Date-header into a timestamp
  360. *
  361. * @param array dateParts the Date-header split by whitespace
  362. * @return int the timestamp calculated from the header
  363. */
  364. function getTimeStamp($dateParts) {
  365. /* $dateParts[0] == <day of week> Mon, Tue, Wed
  366. * $dateParts[1] == <day of month> 23
  367. * $dateParts[2] == <month> Jan, Feb, Mar
  368. * $dateParts[3] == <year> 1999
  369. * $dateParts[4] == <time> 18:54:23 (HH:MM:SS)
  370. * $dateParts[5] == <from GMT> +0100
  371. * $dateParts[6] == <zone> (EDT)
  372. *
  373. * NOTE: In RFC 822, it states that <day of week> is optional.
  374. * In that case, dateParts[0] would be the <day of month>
  375. * and everything would be bumped up one.
  376. */
  377. /*
  378. * Simply check to see if the first element in the dateParts
  379. * array is an integer or not.
  380. * Since the day of week is optional, this check is needed.
  381. */
  382. if (count($dateParts) <2) {
  383. return -1;
  384. } else if (count($dateParts) ==3) {
  385. if (substr_count($dateParts[0],'-') == 2 &&
  386. substr_count($dateParts[1],':') == 2) {
  387. // dd-Month-yyyy 23:19:05 +0200
  388. // redefine the date
  389. $aDate = explode('-',$dateParts[0]);
  390. $newDate = array($aDate[0],$aDate[1],$aDate[2],$dateParts[1],$dateParts[2]);
  391. $dateParts = $newDate;
  392. }
  393. }
  394. /* remove day of week */
  395. if (!is_numeric(trim($dateParts[0]))) {
  396. $dataParts = array_shift($dateParts);
  397. }
  398. /* calculate timestamp separated from the zone and obs-zone */
  399. $stamp = strtotime(implode (' ', array_splice ($dateParts,0,4)));
  400. if (!isset($dateParts[0])) {
  401. $dateParts[0] = '+0000';
  402. }
  403. if (!preg_match('/^[+-]{1}[0-9]{4}$/',$dateParts[0])) {
  404. /* zone in obs-zone format */
  405. if (preg_match('/\((.+)\)/',$dateParts[0],$regs)) {
  406. $obs_zone = $regs[1];
  407. } else {
  408. $obs_zone = $dateParts[0];
  409. }
  410. return getGMTSeconds($stamp, $obs_zone);
  411. } else {
  412. return getGMTSeconds($stamp, $dateParts[0]);
  413. }
  414. }
  415. /* I use this function for profiling. Should never be called in
  416. actual versions of SquirrelMail released to public. */
  417. /*
  418. function getmicrotime() {
  419. $mtime = microtime();
  420. $mtime = explode(' ',$mtime);
  421. $mtime = $mtime[1] + $mtime[0];
  422. return ($mtime);
  423. }
  424. */
  425. ?>