1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway UNIX Mail/News <-> FIDO NetMail/EchoMail
4 *
5 * $Id: date.c,v 4.11 2004/08/22 20:19:11 n0ll Exp $
6 *
7 * date() date/time print function
8 *
9 *****************************************************************************
10 * Copyright (C) 1990-2004
11 * _____ _____
12 * | |___ | Martin Junius <mj.at.n0ll.dot.net>
13 * | | | | | | Radiumstr. 18
14 * |_|_|_|@home| D-51069 Koeln, Germany
15 *
16 * This file is part of FIDOGATE.
17 *
18 * FIDOGATE is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 2, or (at your option) any
21 * later version.
22 *
23 * FIDOGATE is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with FIDOGATE; see the file COPYING. If not, write to the Free
30 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31 *****************************************************************************/
32
33 #include "fidogate.h"
34
35
36
37 #define DST_OFFSET 1
38
39 static char *get_tz_name (struct tm *);
40
41
42
43 /*
44 * Get name of current time zone
45 */
get_tz_name(struct tm * tm)46 static char *get_tz_name(struct tm *tm)
47 {
48 #ifdef HAS_STRFTIME
49 static char buf[32];
50
51 strftime(buf, sizeof(buf), "%Z", tm);
52 return buf;
53 #endif
54
55 #ifdef HAS_TM_ZONE
56 return tm->tm_zone;
57 #endif
58
59 #ifdef HAS_TZNAME
60 return tm->tm_isdst > 0 ? tzname[1] : tzname[0];
61 #endif
62 }
63
64
65
66 /*
67 * Format date/time according to strftime() format string
68 */
date(char * fmt,time_t * t)69 char *date(char *fmt, time_t *t)
70 {
71 static char buf[128];
72
73 return date_buf(buf, sizeof(buf), fmt, t);
74 }
75
76
date_buf(char * buf,size_t len,char * fmt,time_t * t)77 char *date_buf(char *buf, size_t len, char *fmt, time_t *t)
78 {
79 TIMEINFO ti;
80 struct tm *tm;
81
82 /* names for weekdays */
83 static char *weekdays[] = {
84 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
85 };
86 /* names for months */
87 static char *months[] = {
88 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
89 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
90 };
91 char *p = buf;
92 char *s, sbuf[16];
93 int hour, min, off;
94 char cc;
95
96 /* Check for invalid time (-1) */
97 if(fmt==NULL && t && *t==-1)
98 return "INVALID";
99
100 GetTimeInfo(&ti);
101 tm = localtime(&ti.time);
102 if(tm->tm_isdst)
103 ti.tzone += DST_OFFSET * 60;
104
105 if(t)
106 ti.time = *t;
107 tm = localtime(&ti.time);
108 if(tm->tm_isdst)
109 ti.tzone -= DST_OFFSET * 60;
110
111 /* Default format string */
112 if(!fmt)
113 fmt = DATE_DEFAULT;
114
115 /*
116 * Partial strftime() format implementation with additional
117 * %O time difference to UTC, format [+-]hhmm,
118 * e.g. +0100 for MET, +0200 for MET DST
119 */
120 *p = 0;
121 while(*fmt)
122 {
123 if(*fmt == '%')
124 {
125 fmt++;
126 switch (*fmt)
127 {
128 case 'a': /* Abbr. weekday */
129 s = weekdays[tm->tm_wday]; break;
130 /* A not implemented */
131 case 'b': /* Abbr. month */
132 s = months[tm->tm_mon]; break;
133 /* B not implemented */
134 /* c not implemented */
135 case 'd': /* Day of month */
136 str_printf(sbuf, sizeof(sbuf), "%02d", tm->tm_mday);
137 s = sbuf; break;
138 case 'H': /* Hour (24h) */
139 str_printf(sbuf, sizeof(sbuf), "%02d", tm->tm_hour);
140 s = sbuf; break;
141 /* I not implemented */
142 case 'j': /* Day of year */
143 str_printf(sbuf, sizeof(sbuf), "%03d", tm->tm_yday);
144 s = sbuf; break;
145 case 'm': /* Month */
146 str_printf(sbuf, sizeof(sbuf), "%02d", tm->tm_mon + 1);
147 s = sbuf; break;
148 case 'M': /* Minutes */
149 str_printf(sbuf, sizeof(sbuf), "%02d", tm->tm_min);
150 s = sbuf; break;
151 /* p not implemented */
152 case 'S': /* Seconds */
153 str_printf(sbuf, sizeof(sbuf), "%02d", tm->tm_sec);
154 s = sbuf; break;
155 /* U not implemented */
156 case 'w': /* Day of week */
157 str_printf(sbuf, sizeof(sbuf), "%d", tm->tm_wday);
158 s = sbuf; break;
159 /* W not implemented */
160 case 'x': /* Date */
161 str_printf(sbuf, sizeof(sbuf), "%s %2d %4d",
162 months[tm->tm_mon],
163 tm->tm_mday, tm->tm_year+1900);
164 s = sbuf; break;
165 case 'X': /* Time */
166 str_printf(sbuf, sizeof(sbuf), "%02d:%02d:%02d",
167 tm->tm_hour, tm->tm_min, tm->tm_sec);
168 s = sbuf; break;
169 case 'y': /* Year 00-99 */
170 str_printf(sbuf, sizeof(sbuf), "%02d", (tm->tm_year % 100) );
171 s = sbuf; break;
172 case 'Y': /* Year 1900 ... */
173 str_printf(sbuf, sizeof(sbuf), "%4d", 1900 + tm->tm_year);
174 s = sbuf; break;
175 case 'Z': /* Time zone */
176 s = get_tz_name(tm); break;
177 /***** Additional %O format *****/
178 case 'O': /* Time diff to UTC */
179 off = - ti.tzone;
180 cc = off >= 0 ? '+' : '-';
181 off = off < 0 ? -off : off;
182 hour = off / 60;
183 min = off % 60;
184 str_printf(sbuf, sizeof(sbuf), "%c%02d%02d", cc, hour, min);
185 s = sbuf;
186 break;
187 default:
188 sbuf[0] = *fmt;
189 sbuf[1] = 0;
190 s = sbuf;
191 break;
192 }
193 }
194 else
195 {
196 sbuf[0] = *fmt;
197 sbuf[1] = 0;
198 s = sbuf;
199 }
200
201 str_append(buf, len, s);
202 fmt++;
203 }
204
205 return buf;
206 }
207