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