8e86e10def4b6a7c28bd905ef80e10ab450440b3
[squirrelmail.git] / functions / date.php
1 <?php
2
3 /**
4 * date.php
5 *
6 * Copyright (c) 1999-2005 The SquirrelMail Project Team
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 *
14 * @version $Id$
15 * @package squirrelmail
16 * @subpackage date
17 */
18
19 /** Load up some useful constants */
20 require_once(SM_PATH . 'functions/constants.php');
21
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 */
29 function getGMTSeconds($stamp, $tzc) {
30 /* date couldn't be parsed */
31 if ($stamp == -1) {
32 return -1;
33 }
34 /* timezone correction, expressed as `shhmm' */
35 switch($tzc)
36 {
37 case 'Pacific':
38 case 'PST':
39 $tzc = '-0800';
40 break;
41 case 'Mountain':
42 case 'MST':
43 case 'PDT':
44 $tzc = '-0700';
45 break;
46 case 'Central':
47 case 'CST':
48 case 'MDT':
49 $tzc = '-0600';
50 break;
51 case 'Eastern':
52 case 'EST':
53 case 'CDT':
54 $tzc = '-0500';
55 break;
56 case 'EDT':
57 $tzc = '-0400';
58 break;
59 case 'GMT':
60 $tzc = '+0000';
61 break;
62 case 'BST':
63 case 'MET':
64 case 'CET':
65 $tzc = '+0100';
66 break;
67 case 'EET':
68 case 'IST':
69 case 'MET DST':
70 case 'METDST':
71 $tzc = '+0200';
72 break;
73 case 'HKT':
74 $tzc = '+0800';
75 break;
76 case 'JST':
77 case 'KST':
78 $tzc = '+0900';
79 break;
80 }
81 $neg = false;
82 if (substr($tzc, 0, 1) == '-') {
83 $neg = true;
84 } else if (substr($tzc, 0, 1) != '+') {
85 $tzc = '+'.$tzc;
86 }
87 $hh = substr($tzc,1,2);
88 $mm = substr($tzc,3,2);
89 $iTzc = ($hh * 60 + $mm) * 60;
90 if ($neg) $iTzc = -1 * (int) $iTzc;
91 /* stamp in gmt */
92 $stamp -= $iTzc;
93 /** now find what the server is at **/
94 $current = date('Z', time());
95 /* stamp in local timezone */
96 $stamp += $current;
97
98 return $stamp;
99 }
100
101 /**
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 */
111 function getDayName( $day_number ) {
112
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 }
140
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 */
146 function 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
176
177 /**
178 * Returns the (localized) string for a given month number.
179 *
180 * @param string month_number the month number (01..12)
181 * @return string the month name in human readable form
182 */
183 function 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 }
226
227 /**
228 * Returns the (localized) string for a given month number,
229 * short representation.
230 *
231 * @param string month_number the month number (01..12)
232 * @return string the shortened month in human readable form
233 */
234 function 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
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 */
285 function date_intl( $date_format, $stamp ) {
286 $ret = str_replace( array('D','F','l','M'), array('$1','$2','$3','$4'), $date_format );
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
290 $aParts = explode('#',$ret);
291 $ret = str_replace(array('$1','$4','$2','$3',), array(getDayAbrv($aParts[0]),
292 getMonthAbrv($aParts[1]),
293 getMonthName($aParts[1]),
294 getDayName($aParts[0])),
295 $aParts[2]);
296 return( $ret );
297 }
298
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 */
307 function getLongDateString( $stamp ) {
308
309 global $hour_format;
310
311 if ($stamp == -1) {
312 return '';
313 }
314
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 }
320
321 return( date_intl( $date_format, $stamp ) );
322
323 }
324
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 */
335 function getDateString( $stamp ) {
336
337 global $invert_time, $hour_format, $show_full_date;
338
339 if ( $stamp == -1 ) {
340 return '';
341 }
342
343 $now = time();
344
345 $dateZ = date('Z', $now );
346
347 // FIXME: isn't this obsolete and introduced as a terrible workaround
348 // for bugs at other places which are fixed a long time ago?
349 if ($invert_time) {
350 $dateZ = - $dateZ;
351 }
352
353 // calculate when it was midnight and when it will be,
354 // in order to display dates differently if they're 'today'
355 $midnight = $now - ($now % 86400) - $dateZ;
356 // this is to correct if after calculations midnight is more than
357 // one whole day away.
358 if ($now - $midnight > 86400) {
359 $midnight += 86400;
360 }
361 $nextmid = $midnight + 86400;
362
363 if (($show_full_date == 1) || ($nextmid < $stamp)) {
364 $date_format = _("M j, Y");
365 } else if ($midnight < $stamp) {
366 /* Today */
367 if ( $hour_format == SMPREF_TIME_12HR ) {
368 $date_format = _("g:i a");
369 } else {
370 $date_format = _("G:i");
371 }
372 } else if ($midnight - 518400 < $stamp) {
373 /* This week */
374 if ( $hour_format == SMPREF_TIME_12HR ) {
375 $date_format = _("D, g:i a");
376 } else {
377 $date_format = _("D, G:i");
378 }
379 } else {
380 /* before this week */
381 $date_format = _("M j, Y");
382 }
383
384 return( date_intl( $date_format, $stamp ) );
385 }
386
387 /**
388 * Decodes a RFC 822 Date-header into a timestamp
389 *
390 * @param array dateParts the Date-header split by whitespace
391 * @return int the timestamp calculated from the header
392 */
393 function getTimeStamp($dateParts) {
394 /** $dateParts[0] == <day of week> Mon, Tue, Wed
395 ** $dateParts[1] == <day of month> 23
396 ** $dateParts[2] == <month> Jan, Feb, Mar
397 ** $dateParts[3] == <year> 1999
398 ** $dateParts[4] == <time> 18:54:23 (HH:MM:SS)
399 ** $dateParts[5] == <from GMT> +0100
400 ** $dateParts[6] == <zone> (EDT)
401 **
402 ** NOTE: In RFC 822, it states that <day of week> is optional.
403 ** In that case, dateParts[0] would be the <day of month>
404 ** and everything would be bumped up one.
405 **/
406
407 /*
408 * Simply check to see if the first element in the dateParts
409 * array is an integer or not.
410 * Since the day of week is optional, this check is needed.
411 */
412 if (count($dateParts) <2) {
413 return -1;
414 } else if (count($dateParts) ==3) {
415 if (substr_count($dateParts[0],'-') == 2 &&
416 substr_count($dateParts[1],':') == 2) {
417 // dd-Month-yyyy 23:19:05 +0200
418 // redefine the date
419 $aDate = explode('-',$dateParts[0]);
420 $newDate = array($aDate[0],$aDate[1],$aDate[2],$dateParts[1],$dateParts[2]);
421 $dateParts = $newDate;
422 }
423 }
424
425 /* remove day of week */
426 if (!is_numeric(trim($dateParts[0]))) {
427 $dataParts = array_shift($dateParts);
428 }
429 /* calculate timestamp separated from the zone and obs-zone */
430 $stamp = strtotime(implode (' ', array_splice ($dateParts,0,4)));
431 if (!isset($dateParts[0])) {
432 $dateParts[0] = '+0000';
433 }
434
435 if (!preg_match('/^[+-]{1}[0-9]{4}$/',$dateParts[0])) {
436 /* zone in obs-zone format */
437 if (preg_match('/\((.+)\)/',$dateParts[0],$regs)) {
438 $obs_zone = $regs[1];
439 } else {
440 $obs_zone = $dateParts[0];
441 }
442 return getGMTSeconds($stamp, $obs_zone);
443 } else {
444 return getGMTSeconds($stamp, $dateParts[0]);
445 }
446 }
447
448 /* I use this function for profiling. Should never be called in
449 actual versions of squirrelmail released to public. */
450 /*
451 function getmicrotime() {
452 $mtime = microtime();
453 $mtime = explode(' ',$mtime);
454 $mtime = $mtime[1] + $mtime[0];
455 return ($mtime);
456 }
457 */
458 ?>