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