e2712366d854e809357be6145a27cfcd3979563e
[reactos.git] / reactos / apps / utils / cmd / date.c
1 /*
2 * DATE.C - date internal command.
3 *
4 *
5 * History:
6 *
7 * 08 Jul 1998 (John P. Price)
8 * started.
9 *
10 * 20 Jul 1998 (John P. Price)
11 * corrected number of days for December from 30 to 31.
12 * (Thanx to Steffen Kaiser for bug report)
13 *
14 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
15 * added config.h include
16 *
17 * 29-Jul-1998 (Rob Lake)
18 * fixed stand-alone mode.
19 * Added Pacific C compatible dos_getdate functions
20 *
21 * 09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
22 * Added locale support
23 *
24 * 23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
25 * Unicode and redirection safe!
26 *
27 * 04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
28 * Fixed date input bug.
29 */
30
31 #define WIN32_LEAN_AND_MEAN
32
33 #include "config.h"
34
35 #ifdef INCLUDE_CMD_DATE
36
37 #include <windows.h>
38 #include <tchar.h>
39 #include <string.h>
40 #include <ctype.h>
41
42 #include "cmd.h"
43
44
45 static WORD awMonths[2][13] =
46 {
47 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
48 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
49 };
50
51
52 static VOID
53 PrintDate (VOID)
54 {
55 #if 0
56 SYSTEMTIME st;
57
58 GetLocalTime (&st);
59
60 switch (nDateFormat)
61 {
62 case 0: /* mmddyy */
63 default:
64 ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
65 aszDayNames[st.wDayOfWeek], st.wMonth, cDateSeparator, st.wDay, cDateSeparator, st.wYear);
66 break;
67
68 case 1: /* ddmmyy */
69 ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
70 aszDayNames[st.wDayOfWeek], st.wDay, cDateSeparator, st.wMonth, cDateSeparator, st.wYear);
71 break;
72
73 case 2: /* yymmdd */
74 ConOutPrintf (_T("Current date is: %s %04d%c%02d%c%02d\n"),
75 aszDayNames[st.wDayOfWeek], st.wYear, cDateSeparator, st.wMonth, cDateSeparator, st.wDay);
76 break;
77 }
78 #endif
79 TCHAR szDate[32];
80
81 GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL,
82 szDate, sizeof (szDate));
83 ConOutPrintf (_T("Current date is: %s\n"), szDate);
84 }
85
86
87 static VOID
88 PrintDateString (VOID)
89 {
90 switch (nDateFormat)
91 {
92 case 0: /* mmddyy */
93 default:
94 ConOutPrintf (_T("Enter new date (mm%cdd%cyyyy): "),
95 cDateSeparator, cDateSeparator);
96 break;
97
98 case 1: /* ddmmyy */
99 ConOutPrintf (_T("Enter new date (dd%cmm%cyyyy): "),
100 cDateSeparator, cDateSeparator);
101 break;
102
103 case 2: /* yymmdd */
104 ConOutPrintf (_T("Enter new date (yyyy%cmm%cdd): "),
105 cDateSeparator, cDateSeparator);
106 break;
107 }
108 }
109
110
111 static BOOL
112 ReadNumber (LPTSTR *s, LPWORD lpwValue)
113 {
114 if (_istdigit (**s))
115 {
116 while (_istdigit (**s))
117 {
118 *lpwValue = *lpwValue * 10 + **s - _T('0');
119 (*s)++;
120 }
121 return TRUE;
122 }
123 return FALSE;
124 }
125
126
127 static BOOL
128 ReadSeparator (LPTSTR *s)
129 {
130 if (**s == _T('/') || **s == _T('-') || **s == cDateSeparator)
131 {
132 (*s)++;
133 return TRUE;
134 }
135 return FALSE;
136 }
137
138
139 static BOOL
140 ParseDate (LPTSTR s)
141 {
142 SYSTEMTIME d;
143 unsigned char leap;
144 LPTSTR p = s;
145
146 if (!*s)
147 return TRUE;
148
149 GetLocalTime (&d);
150
151 d.wYear = 0;
152 d.wDay = 0;
153 d.wMonth = 0;
154
155 switch (nDateFormat)
156 {
157 case 0: /* mmddyy */
158 default:
159 if (!ReadNumber (&p, &d.wMonth))
160 return FALSE;
161 if (!ReadSeparator (&p))
162 return FALSE;
163 if (!ReadNumber (&p, &d.wDay))
164 return FALSE;
165 if (!ReadSeparator (&p))
166 return FALSE;
167 if (!ReadNumber (&p, &d.wYear))
168 return FALSE;
169 break;
170
171 case 1: /* ddmmyy */
172 if (!ReadNumber (&p, &d.wDay))
173 return FALSE;
174 if (!ReadSeparator (&p))
175 return FALSE;
176 if (!ReadNumber (&p, &d.wMonth))
177 return FALSE;
178 if (!ReadSeparator (&p))
179 return FALSE;
180 if (!ReadNumber (&p, &d.wYear))
181 return FALSE;
182 break;
183
184 case 2: /* yymmdd */
185 if (!ReadNumber (&p, &d.wYear))
186 return FALSE;
187 if (!ReadSeparator (&p))
188 return FALSE;
189 if (!ReadNumber (&p, &d.wMonth))
190 return FALSE;
191 if (!ReadSeparator (&p))
192 return FALSE;
193 if (!ReadNumber (&p, &d.wDay))
194 return FALSE;
195 break;
196 }
197
198 /* if only entered two digits:
199 /* assume 2000's if value less than 80 */
200 /* assume 1900's if value greater or equal 80 */
201 if (d.wYear <= 99)
202 {
203 if (d.wYear >= 80)
204 d.wYear = 1900 + d.wYear;
205 else
206 d.wYear = 2000 + d.wYear;
207 }
208
209 leap = (!(d.wYear % 4) && (d.wYear % 100)) || !(d.wYear % 400);
210
211 if ((d.wMonth >= 1 && d.wMonth <= 12) &&
212 (d.wDay >= 1 && d.wDay <= awMonths[leap][d.wMonth]) &&
213 (d.wYear >= 1980 && d.wYear <= 2099))
214 {
215 SetLocalTime (&d);
216 return TRUE;
217 }
218
219 return FALSE;
220 }
221
222
223 INT cmd_date (LPTSTR cmd, LPTSTR param)
224 {
225 LPTSTR *arg;
226 INT argc;
227 INT i;
228 BOOL bPrompt = TRUE;
229 INT nDateString = -1;
230
231 if (!_tcsncmp (param, _T("/?"), 2))
232 {
233 ConOutPuts (_T("Displays or sets the date.\n\n"
234 "DATE [/T][date]\n\n"
235 " /T display only\n\n"
236 "Type DATE without parameters to display the current date setting and\n"
237 "a prompt for a new one. Press ENTER to keep the same date."));
238 return 0;
239 }
240
241 /* build parameter array */
242 arg = split (param, &argc);
243
244 /* check for options */
245 for (i = 0; i < argc; i++)
246 {
247 if (_tcsicmp (arg[i], _T("/t")) == 0)
248 bPrompt = FALSE;
249 if ((*arg[i] != _T('/')) && (nDateString == -1))
250 nDateString = i;
251 }
252
253 if (nDateString == -1)
254 PrintDate ();
255
256 if (!bPrompt)
257 {
258 freep (arg);
259 return 0;
260 }
261
262 if (nDateString == -1)
263 {
264 while (TRUE) /* forever loop */
265 {
266 TCHAR s[40];
267
268 PrintDateString ();
269 ConInString (s, 40);
270 #ifdef _DEBUG
271 DebugPrintf ("\'%s\'\n", s);
272 #endif
273 while (*s && s[_tcslen (s) - 1] < ' ')
274 s[_tcslen (s) - 1] = '\0';
275 if (ParseDate (s))
276 {
277 freep (arg);
278 return 0;
279 }
280 ConErrPuts ("Invalid date.");
281 }
282 }
283 else
284 {
285 if (ParseDate (arg[nDateString]))
286 {
287 freep (arg);
288 return 0;
289 }
290 ConErrPuts ("Invalid date.");
291 }
292
293 freep (arg);
294
295 return 0;
296 }
297 #endif
298