xref: /reactos/base/shell/cmd/date.c (revision 201f00ab)
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)
22  *        Added locale support
23  *
24  *    23-Jan-1999 (Eric Kohl)
25  *        Unicode and redirection safe!
26  *
27  *    04-Feb-1999 (Eric Kohl)
28  *        Fixed date input bug.
29  *
30  *    03-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
31  *        Remove all hardcoded strings in En.rc
32  */
33 
34 #include "precomp.h"
35 
36 #ifdef INCLUDE_CMD_DATE
37 
38 
39 static WORD awMonths[2][13] =
40 {
41     {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
42     {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
43 };
44 
45 
46 static VOID
47 PromptDateString(VOID)
48 {
49     switch (nDateFormat)
50     {
51         case 0: /* mmddyy */
52         default:
53             ConOutResPrintf(STRING_DATE_HELP1, cDateSeparator, cDateSeparator);
54             break;
55 
56         case 1: /* ddmmyy */
57             ConOutResPrintf(STRING_DATE_HELP2, cDateSeparator, cDateSeparator);
58             break;
59 
60         case 2: /* yymmdd */
61             ConOutResPrintf(STRING_DATE_HELP3, cDateSeparator, cDateSeparator);
62             break;
63     }
64 }
65 
66 static BOOL
67 ReadNumber (LPTSTR *s, LPWORD lpwValue)
68 {
69     if (_istdigit (**s))
70     {
71         while (_istdigit (**s))
72         {
73             *lpwValue = *lpwValue * 10 + **s - _T('0');
74             (*s)++;
75         }
76         return TRUE;
77     }
78     return FALSE;
79 }
80 
81 static BOOL
82 ReadSeparator (LPTSTR *s)
83 {
84     if (**s == _T('/') || **s == _T('-') || **s == cDateSeparator)
85     {
86         (*s)++;
87         return TRUE;
88     }
89     return FALSE;
90 }
91 
92 static BOOL
93 ParseDate (LPTSTR s)
94 {
95     SYSTEMTIME d;
96     unsigned char leap;
97     LPTSTR p = s;
98 
99     if (!*s)
100         return TRUE;
101 
102     GetLocalTime (&d);
103 
104     d.wYear = 0;
105     d.wDay = 0;
106     d.wMonth = 0;
107 
108     switch (nDateFormat)
109     {
110         case 0: /* mmddyy */
111         default:
112             if (!ReadNumber (&p, &d.wMonth))
113                 return FALSE;
114             if (!ReadSeparator (&p))
115                 return FALSE;
116             if (!ReadNumber (&p, &d.wDay))
117                 return FALSE;
118             if (!ReadSeparator (&p))
119                 return FALSE;
120             if (!ReadNumber (&p, &d.wYear))
121                 return FALSE;
122             break;
123 
124         case 1: /* ddmmyy */
125             if (!ReadNumber (&p, &d.wDay))
126                 return FALSE;
127             if (!ReadSeparator (&p))
128                 return FALSE;
129             if (!ReadNumber (&p, &d.wMonth))
130                 return FALSE;
131             if (!ReadSeparator (&p))
132                 return FALSE;
133             if (!ReadNumber (&p, &d.wYear))
134                 return FALSE;
135             break;
136 
137         case 2: /* yymmdd */
138             if (!ReadNumber (&p, &d.wYear))
139                 return FALSE;
140             if (!ReadSeparator (&p))
141                 return FALSE;
142             if (!ReadNumber (&p, &d.wMonth))
143                 return FALSE;
144             if (!ReadSeparator (&p))
145                 return FALSE;
146             if (!ReadNumber (&p, &d.wDay))
147                 return FALSE;
148             break;
149     }
150 
151     /* if only entered two digits: */
152     /*   assume 2000's if value less than 80 */
153     /*   assume 1900's if value greater or equal 80 */
154     if (d.wYear <= 99)
155     {
156         if (d.wYear >= 80)
157             d.wYear = 1900 + d.wYear;
158         else
159             d.wYear = 2000 + d.wYear;
160     }
161 
162     leap = (!(d.wYear % 4) && (d.wYear % 100)) || !(d.wYear % 400);
163 
164     if ((d.wMonth >= 1 && d.wMonth <= 12) &&
165         (d.wDay >= 1 && d.wDay <= awMonths[leap][d.wMonth]) &&
166         (d.wYear >= 1980 && d.wYear <= 2099))
167     {
168         SetLocalTime (&d);
169         return TRUE;
170     }
171 
172     return FALSE;
173 }
174 
175 
176 INT cmd_date(LPTSTR param)
177 {
178     LPTSTR* arg;
179     INT argc;
180     INT i;
181     BOOL bPrompt = TRUE;
182     INT nDateString = -1;
183     TCHAR szDate[40];
184 
185     if (!_tcsncmp(param, _T("/?"), 2))
186     {
187         ConOutResPaging(TRUE, STRING_DATE_HELP4);
188         return 0;
189     }
190 
191     nErrorLevel = 0;
192 
193     /* Build the parameter array */
194     arg = split(param, &argc, FALSE, FALSE);
195 
196     /* Check for options */
197     for (i = 0; i < argc; i++)
198     {
199         if (bEnableExtensions && (_tcsicmp(arg[i], _T("/T")) == 0))
200             bPrompt = FALSE;
201 
202         if ((*arg[i] != _T('/')) && (nDateString == -1))
203             nDateString = i;
204     }
205 
206     if (nDateString == -1)
207     {
208         ConOutResPuts(STRING_DATE_NOW);
209         ConOutPrintf(_T("%s\n"), GetDateString());
210     }
211 
212     if (!bPrompt)
213     {
214         freep(arg);
215         return 0;
216     }
217 
218     while (TRUE)
219     {
220         if (nDateString == -1)
221         {
222             PromptDateString();
223             ConInString(szDate, ARRAYSIZE(szDate));
224 
225             TRACE("\'%s\'\n", debugstr_aw(szDate));
226 
227             while (*szDate && szDate[_tcslen(szDate) - 1] < _T(' '))
228                 szDate[_tcslen(szDate) - 1] = _T('\0');
229 
230             if (ParseDate(szDate))
231             {
232                 freep(arg);
233                 return 0;
234             }
235         }
236         else
237         {
238             if (ParseDate(arg[nDateString]))
239             {
240                 freep(arg);
241                 return 0;
242             }
243 
244             /* Force input the next time around */
245             nDateString = -1;
246         }
247 
248         ConErrResPuts(STRING_DATE_ERROR);
249         nErrorLevel = 1;
250     }
251 
252     freep(arg);
253     return 0;
254 }
255 #endif /* INCLUDE_CMD_DATE */
256 
257 /* EOF */
258