0
|
1 |
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
// All rights reserved.
|
|
3 |
// This component and the accompanying materials are made available
|
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
|
5 |
// which accompanies this distribution, and is available
|
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
// e32\euser\us_parse.cpp
|
|
15 |
//
|
|
16 |
//
|
|
17 |
|
|
18 |
#include "us_std.h"
|
|
19 |
|
|
20 |
class TStringToDateTime
|
|
21 |
{
|
|
22 |
public:
|
|
23 |
TStringToDateTime(const TDesC& aDes,TInt aCenturyOffset);
|
|
24 |
TInt Parse(TTime& aTime);
|
|
25 |
enum {ETimePresent=1,EDatePresent};
|
|
26 |
private:
|
|
27 |
// tokens
|
|
28 |
enum {EDec=-12,ENov,EOct,ESep,EAug,EJul,EJun,EMay,EApr,EMar,EFeb,EJan};
|
|
29 |
enum {ETokenAm=-19,ETokenPm};
|
|
30 |
enum TDateSeparators{ESlash=-39,EDash,EComma,ESpace,EDateLocale1,EDateLocale2};
|
|
31 |
enum TTimeSeparators{EColon=-49,EDot,ETimeLocale1,ETimeLocale2};
|
|
32 |
enum TDecimalSeparators{EDecimalLocale=-59};
|
|
33 |
enum {EErrorToken=-99,ENullToken=-100};
|
|
34 |
//
|
|
35 |
enum {ENumberOfDateSep=6,ENumberOfTimeSep=4,EMaxTokens=27};
|
|
36 |
enum {EFirstDateSep=ESlash,ELastDateSep=EDateLocale2,EFirstTimeSep=EColon,ELastTimeSep=ETimeLocale2};
|
|
37 |
private:
|
|
38 |
TInt NextToken(TInt& aTokenLen);
|
|
39 |
void StripSpaceTokens();
|
|
40 |
TInt CrackTokenFormula();
|
|
41 |
TInt GetDate(TInt aFormulaPos,TInt& aTokenCount);
|
|
42 |
TInt GetTime(TInt aFormulaPos,TInt& aTokenCount);
|
|
43 |
//
|
|
44 |
TInt GetSeparatorToken(TChar aChar) const;
|
|
45 |
TBool IsTimeSeparator(TChar aChar) const;
|
|
46 |
TBool IsDateSeparator(TChar aChar) const;
|
|
47 |
TBool IsDecimalSeparator(TChar aChar) const;
|
|
48 |
TBool IsSeparator(TChar aChar) const;
|
|
49 |
TBool IsSeparator(TInt aToken) const;
|
|
50 |
inline TBool IsTimeSeparator(TInt aToken) const;
|
|
51 |
inline TBool IsDateSeparator(TInt aToken) const;
|
|
52 |
TBool IsDecimalSeparator(TInt aToken) const;
|
|
53 |
inline TBool IsAmPm(TInt aToken) const;
|
|
54 |
inline TBool IsAlphaMonth(TInt aToken) const;
|
|
55 |
private:
|
|
56 |
TLex iLex;
|
|
57 |
TInt iCenturyOffset;
|
|
58 |
TDateFormat iDateFormat;
|
|
59 |
TChar iTimeSepChars[ENumberOfTimeSep];
|
|
60 |
TChar iDateSepChars[ENumberOfDateSep];
|
|
61 |
TChar iDecSepChar;
|
|
62 |
TDateTime iDateTime;
|
|
63 |
TInt iCount;
|
|
64 |
TInt iFormula[EMaxTokens];// 27 max possible with valid des (including spaces):" 10 : 00 : 00 . 000000 pm 6 / 12 / 99 "
|
|
65 |
TUint8 iTokenLen[EMaxTokens];
|
|
66 |
};
|
|
67 |
|
|
68 |
inline TBool TStringToDateTime::IsTimeSeparator(TInt aToken) const
|
|
69 |
{
|
|
70 |
return(aToken >= EFirstTimeSep && aToken <=ELastTimeSep);
|
|
71 |
}
|
|
72 |
inline TBool TStringToDateTime::IsDateSeparator(TInt aToken) const
|
|
73 |
{
|
|
74 |
return(aToken>=EFirstDateSep && aToken<=ELastDateSep);
|
|
75 |
}
|
|
76 |
inline TBool TStringToDateTime::IsAmPm(TInt aToken) const
|
|
77 |
{
|
|
78 |
return(aToken==ETokenAm || aToken==ETokenPm);
|
|
79 |
}
|
|
80 |
inline TBool TStringToDateTime::IsAlphaMonth(TInt aToken) const
|
|
81 |
{
|
|
82 |
return (aToken>=EDec && aToken<=EJan);
|
|
83 |
}
|
|
84 |
|
|
85 |
inline TBool TStringToDateTime::IsDecimalSeparator(TChar aChar) const
|
|
86 |
{
|
|
87 |
return(aChar==iDecSepChar);
|
|
88 |
}
|
|
89 |
inline TBool TStringToDateTime::IsDecimalSeparator(TInt aToken) const
|
|
90 |
{
|
|
91 |
return(aToken==EDecimalLocale);
|
|
92 |
}
|
|
93 |
|
|
94 |
TStringToDateTime::TStringToDateTime(const TDesC& aDes,TInt aCenturyOffset)
|
|
95 |
: iLex(aDes),iCenturyOffset(aCenturyOffset),iDateTime(0,EJanuary,0,0,0,0,0)
|
|
96 |
{
|
|
97 |
|
|
98 |
__ASSERT_ALWAYS(aCenturyOffset>=0 && aCenturyOffset<100,Panic(ETTimeValueOutOfRange));
|
|
99 |
TLocale locale;
|
|
100 |
iDateFormat=locale.DateFormat();
|
|
101 |
|
|
102 |
iTimeSepChars[0]=':';
|
|
103 |
iTimeSepChars[1]='.';
|
|
104 |
iTimeSepChars[2]=locale.TimeSeparator(1);
|
|
105 |
iTimeSepChars[3]=locale.TimeSeparator(2);
|
|
106 |
|
|
107 |
iDateSepChars[0]='/';
|
|
108 |
iDateSepChars[1]='-';
|
|
109 |
iDateSepChars[2]=',';
|
|
110 |
iDateSepChars[3]=' ';
|
|
111 |
iDateSepChars[4]=locale.DateSeparator(1);
|
|
112 |
iDateSepChars[5]=locale.DateSeparator(2);
|
|
113 |
iDecSepChar = locale.DecimalSeparator();
|
|
114 |
}
|
|
115 |
|
|
116 |
TBool TStringToDateTime::IsTimeSeparator(TChar aChar) const
|
|
117 |
{
|
|
118 |
|
|
119 |
for (TInt ii=0;ii<ENumberOfTimeSep;++ii)
|
|
120 |
if (aChar==iTimeSepChars[ii])
|
|
121 |
return ETrue;
|
|
122 |
return(EFalse);
|
|
123 |
}
|
|
124 |
|
|
125 |
TBool TStringToDateTime::IsDateSeparator(TChar aChar) const
|
|
126 |
{
|
|
127 |
|
|
128 |
for (TInt ii=0;ii<ENumberOfDateSep;++ii)
|
|
129 |
if (aChar==iDateSepChars[ii])
|
|
130 |
return ETrue;
|
|
131 |
return(EFalse);
|
|
132 |
}
|
|
133 |
|
|
134 |
TBool TStringToDateTime::IsSeparator(TChar aChar) const
|
|
135 |
{
|
|
136 |
|
|
137 |
return(IsTimeSeparator(aChar) || IsDateSeparator(aChar) || IsDecimalSeparator(aChar));
|
|
138 |
}
|
|
139 |
|
|
140 |
TBool TStringToDateTime::IsSeparator(TInt aToken) const
|
|
141 |
{
|
|
142 |
|
|
143 |
return(IsTimeSeparator(aToken) || IsDateSeparator(aToken));
|
|
144 |
}
|
|
145 |
|
|
146 |
TInt TStringToDateTime::GetSeparatorToken(TChar aChar) const
|
|
147 |
{
|
|
148 |
|
|
149 |
TInt ii=0;
|
|
150 |
for (ii=0;ii<ENumberOfDateSep;++ii)
|
|
151 |
if (aChar == iDateSepChars[ii])
|
|
152 |
return(EFirstDateSep+ii);
|
|
153 |
for (ii=0;ii<ENumberOfTimeSep;++ii)
|
|
154 |
if (aChar == iTimeSepChars[ii])
|
|
155 |
return(EFirstTimeSep+ii);
|
|
156 |
if (aChar == iDecSepChar)
|
|
157 |
return(EDecimalLocale);
|
|
158 |
return(ENullToken);
|
|
159 |
}
|
|
160 |
|
|
161 |
void TStringToDateTime::StripSpaceTokens()
|
|
162 |
// Removes excess space tokens from the formula
|
|
163 |
// The end of the formula is marked with a Null token
|
|
164 |
{
|
|
165 |
|
|
166 |
TInt t = 0;
|
|
167 |
for (TInt s = 0 ; s < iCount ; ++s)
|
|
168 |
{
|
|
169 |
if (iFormula[s]==ESpace &&
|
|
170 |
(IsSeparator(iFormula[s-1]) || s == iCount-1 || IsSeparator(iFormula[s+1]) || IsAmPm(iFormula[s+1])))
|
|
171 |
continue;// Skip unwanted space token
|
|
172 |
iFormula[t]=iFormula[s];
|
|
173 |
iTokenLen[t]=iTokenLen[s];
|
|
174 |
++t;
|
|
175 |
}
|
|
176 |
iCount=t;
|
|
177 |
iFormula[t]=ENullToken;
|
|
178 |
}
|
|
179 |
|
|
180 |
TInt TStringToDateTime::CrackTokenFormula()
|
|
181 |
{
|
|
182 |
|
|
183 |
if (iCount==0)
|
|
184 |
return KErrArgument;// Nothing to read
|
|
185 |
TInt token0=iFormula[0];
|
|
186 |
TInt token1=iFormula[1];
|
|
187 |
TInt numberOfTokens;
|
|
188 |
TInt dummy=0;
|
|
189 |
TInt error;
|
|
190 |
if (IsDateSeparator(token1) || IsAlphaMonth(token0))
|
|
191 |
{// Assume formula is a Date or DateTime
|
|
192 |
if ((error=GetDate(0,numberOfTokens))!=EDatePresent)
|
|
193 |
return error;
|
|
194 |
numberOfTokens+=1;// Space char between the Date & Time
|
|
195 |
return(GetTime(numberOfTokens,dummy));
|
|
196 |
}
|
|
197 |
else if (IsTimeSeparator(token1) || IsAmPm(token1))
|
|
198 |
{// Assume formula is a Time or TimeDate
|
|
199 |
if ((error=GetTime(0,numberOfTokens))!=ETimePresent)
|
|
200 |
return error;
|
|
201 |
numberOfTokens+=1;// Space char between the Time & Date
|
|
202 |
return(GetDate(numberOfTokens,dummy));
|
|
203 |
}
|
|
204 |
else
|
|
205 |
return(KErrArgument);
|
|
206 |
}
|
|
207 |
|
|
208 |
TInt TStringToDateTime::GetDate(TInt aOffset,TInt& aTokenCount)
|
|
209 |
// if aOffset == 0 then Date or DateTime format
|
|
210 |
// if aOffset != 0 then TimeDate format
|
|
211 |
{
|
|
212 |
|
|
213 |
TInt relativeCount=iCount;
|
|
214 |
if (aOffset!=0)// aFormat==ETimeDate
|
|
215 |
{
|
|
216 |
relativeCount-=aOffset;
|
|
217 |
if (relativeCount<=-1)
|
|
218 |
return(ETimePresent);
|
|
219 |
}
|
|
220 |
TInt numberOfDateFields=0;
|
|
221 |
if (relativeCount==3)
|
|
222 |
numberOfDateFields=2;
|
|
223 |
else if (relativeCount==5)
|
|
224 |
numberOfDateFields=3;
|
|
225 |
else if (aOffset==0)
|
|
226 |
{// DateTime
|
|
227 |
if (IsTimeSeparator(iFormula[5]) || IsAmPm(iFormula[5]))
|
|
228 |
numberOfDateFields=2;
|
|
229 |
else
|
|
230 |
numberOfDateFields=3;
|
|
231 |
}
|
|
232 |
else// (aOffset!=0)
|
|
233 |
{// Date
|
|
234 |
if (relativeCount==3)
|
|
235 |
numberOfDateFields=2;
|
|
236 |
else if (relativeCount==5)
|
|
237 |
numberOfDateFields=3;
|
|
238 |
else
|
|
239 |
return(KErrArgument);
|
|
240 |
}
|
|
241 |
|
|
242 |
if (!IsDateSeparator(iFormula[1+aOffset]))
|
|
243 |
return(KErrArgument);
|
|
244 |
if (numberOfDateFields==2)
|
|
245 |
{
|
|
246 |
if (aOffset!=0 && relativeCount!=3)// ie TimeDate
|
|
247 |
return(KErrArgument);
|
|
248 |
}
|
|
249 |
if (numberOfDateFields==3)
|
|
250 |
{
|
|
251 |
if (aOffset!=0 && relativeCount!=5)// ie TimeDate
|
|
252 |
return(KErrArgument);
|
|
253 |
if (!IsDateSeparator(iFormula[3+aOffset]))
|
|
254 |
return(KErrArgument);
|
|
255 |
}
|
|
256 |
|
|
257 |
// A month will always be in the first two fields // DMY MDY YMD
|
|
258 |
TBool alphaMonth=(IsAlphaMonth(iFormula[0+aOffset]) || IsAlphaMonth(iFormula[2+aOffset]) );
|
|
259 |
|
|
260 |
TInt dayIndex;
|
|
261 |
TInt monthIndex;
|
|
262 |
TInt yearIndex=4;// Reset if Japanese
|
|
263 |
|
|
264 |
if (iDateFormat==EDateJapanese)
|
|
265 |
{// 1996 feb 3
|
|
266 |
if (numberOfDateFields==2)
|
|
267 |
{
|
|
268 |
monthIndex=0;
|
|
269 |
dayIndex=2;
|
|
270 |
}
|
|
271 |
else
|
|
272 |
{
|
|
273 |
yearIndex=0;
|
|
274 |
monthIndex=2;
|
|
275 |
dayIndex=4;
|
|
276 |
}
|
|
277 |
}
|
|
278 |
else if (IsAlphaMonth(iFormula[0+aOffset])
|
|
279 |
|| (!alphaMonth && iDateFormat==EDateAmerican))// Amer Euro
|
|
280 |
{// feb 3 1996 valid Amer or Euro format // 2 3 1996 Amer
|
|
281 |
monthIndex=0;
|
|
282 |
dayIndex=2;
|
|
283 |
}
|
|
284 |
else
|
|
285 |
{// 3 feb 1996 valid Amer or Euro format // 3 2 1996 Euro
|
|
286 |
__ASSERT_DEBUG(
|
|
287 |
IsAlphaMonth(iFormula[2+aOffset]) ||
|
|
288 |
(!alphaMonth && iDateFormat==EDateEuropean),User::Invariant());
|
|
289 |
monthIndex=2;
|
|
290 |
dayIndex=0;
|
|
291 |
}
|
|
292 |
|
|
293 |
TTime timeNow;
|
|
294 |
timeNow.HomeTime();
|
|
295 |
TDateTime now=timeNow.DateTime();
|
|
296 |
TInt currentCentury=((now.Year()/100)*100);// Integer arithmetic
|
|
297 |
TInt currentTwoDigitYear=now.Year()-currentCentury;
|
|
298 |
|
|
299 |
TInt year=0;
|
|
300 |
if (numberOfDateFields==3)// then year value exists
|
|
301 |
{
|
|
302 |
year=iFormula[yearIndex+aOffset];
|
|
303 |
if (year<0)// ie a token has been returned as a year
|
|
304 |
return(KErrArgument);
|
|
305 |
else if (iTokenLen[yearIndex+aOffset]<=2)
|
|
306 |
{
|
|
307 |
if (currentTwoDigitYear>=iCenturyOffset)
|
|
308 |
{
|
|
309 |
if (year>=00 && year<iCenturyOffset)
|
|
310 |
year+=currentCentury+100;// next century
|
|
311 |
else
|
|
312 |
year+=currentCentury;
|
|
313 |
}
|
|
314 |
else
|
|
315 |
{
|
|
316 |
if (year>=00 && year<iCenturyOffset)
|
|
317 |
year+=currentCentury;
|
|
318 |
else
|
|
319 |
year+=currentCentury-100;// last century
|
|
320 |
}
|
|
321 |
}
|
|
322 |
}
|
|
323 |
|
|
324 |
TInt month=iFormula[monthIndex+aOffset];
|
|
325 |
if (IsAlphaMonth(month))
|
|
326 |
month=-month;// alphaMonth is -ve enum token
|
|
327 |
month-=1;// months start at zero
|
|
328 |
|
|
329 |
TInt error;// Set Year, Month and Day
|
|
330 |
if ((error=iDateTime.SetYear(year))==KErrNone)
|
|
331 |
if ((error=iDateTime.SetMonth((TMonth)month))==KErrNone)
|
|
332 |
error=iDateTime.SetDay(iFormula[dayIndex+aOffset]-1);
|
|
333 |
if (error!=KErrNone)
|
|
334 |
return(error);
|
|
335 |
|
|
336 |
|
|
337 |
if (numberOfDateFields==2)
|
|
338 |
aTokenCount=3;
|
|
339 |
else if (numberOfDateFields==3)
|
|
340 |
aTokenCount=5;
|
|
341 |
|
|
342 |
if (aOffset!=0)
|
|
343 |
return(EDatePresent|ETimePresent);
|
|
344 |
return(EDatePresent);
|
|
345 |
}
|
|
346 |
|
|
347 |
TInt TStringToDateTime::GetTime(TInt aOffset,TInt& aTokenCount)
|
|
348 |
// aFormulaPos == 0 Time format or TimeDate format with Time first
|
|
349 |
// aFormulaPos != 0 Date preceeds Time i.e. DateTime format
|
|
350 |
// 7 formats 10:00:00.012345 // 10:00:00.012345pm // 10:00:00pm // 10:00:00 // 10:00pm // 10:00 // 10pm
|
|
351 |
// offset and relativeCount allow this function to check times
|
|
352 |
// when both the Time(10:00pm) and DateTime(3-feb-69 10:00pm) formats are used.
|
|
353 |
{
|
|
354 |
|
|
355 |
TInt relativeCount=iCount;
|
|
356 |
if (aOffset!=0)// DateTime // else format==Time
|
|
357 |
{
|
|
358 |
relativeCount-=aOffset;
|
|
359 |
if (relativeCount<=-1)
|
|
360 |
return(EDatePresent);
|
|
361 |
}
|
|
362 |
TInt fields=0;
|
|
363 |
|
|
364 |
if (IsTimeSeparator(iFormula[1+aOffset]) && IsTimeSeparator(iFormula[3+aOffset])&&
|
|
365 |
(IsTimeSeparator(iFormula[5+aOffset]) || IsDecimalSeparator(iFormula[5+aOffset])))
|
|
366 |
{
|
|
367 |
fields=4;// 10:00:00.000000 (am)
|
|
368 |
aTokenCount=7;
|
|
369 |
if (IsAmPm(iFormula[7+aOffset]))
|
|
370 |
aTokenCount+=1;
|
|
371 |
}
|
|
372 |
else if (IsTimeSeparator(iFormula[1+aOffset]) && IsTimeSeparator(iFormula[3+aOffset]))
|
|
373 |
{
|
|
374 |
fields=3;// 10:00:00 (am)
|
|
375 |
aTokenCount=5;
|
|
376 |
if (IsAmPm(iFormula[5+aOffset]))
|
|
377 |
aTokenCount+=1;
|
|
378 |
}
|
|
379 |
else if (IsTimeSeparator(iFormula[1+aOffset]))
|
|
380 |
{
|
|
381 |
fields=2;// 10:00 (am)
|
|
382 |
aTokenCount=3;
|
|
383 |
if (IsAmPm(iFormula[3+aOffset]))
|
|
384 |
aTokenCount+=1;
|
|
385 |
}
|
|
386 |
else if (IsAmPm(iFormula[1+aOffset]))
|
|
387 |
{
|
|
388 |
fields=1;// 10am
|
|
389 |
aTokenCount=2;
|
|
390 |
}
|
|
391 |
if (fields==0 || (fields==4 && relativeCount==6) || (fields==3 && relativeCount==4) || (fields==2 && relativeCount==2))
|
|
392 |
return(KErrArgument);// Colon\DecimalPoint in wrong place 10:00:00. || 10:00: || 10:
|
|
393 |
|
|
394 |
TInt error;
|
|
395 |
if ((error=iDateTime.SetHour(iFormula[0+aOffset]))!=KErrNone)
|
|
396 |
return error;
|
|
397 |
if (fields==2)
|
|
398 |
error=iDateTime.SetMinute(iFormula[2+aOffset]);
|
|
399 |
else if (fields==3)
|
|
400 |
{
|
|
401 |
if ((error=iDateTime.SetMinute(iFormula[2+aOffset]))==KErrNone)
|
|
402 |
error=iDateTime.SetSecond(iFormula[4+aOffset]);
|
|
403 |
}
|
|
404 |
else if (fields==4)
|
|
405 |
{
|
|
406 |
if ((error=iDateTime.SetMinute(iFormula[2+aOffset]))==KErrNone)
|
|
407 |
if ((error=iDateTime.SetSecond(iFormula[4+aOffset]))==KErrNone)
|
|
408 |
error = iDateTime.SetMicroSecond(iFormula[6+aOffset]);
|
|
409 |
}
|
|
410 |
if (error!=KErrNone)
|
|
411 |
return(error);
|
|
412 |
|
|
413 |
TInt ampmIndex=2*fields-1;
|
|
414 |
if (iFormula[ampmIndex+aOffset]==ETokenAm && iDateTime.Hour()==12)
|
|
415 |
error=iDateTime.SetHour(00);// 12am->00 hrs. Ignore 13am
|
|
416 |
else if (iFormula[ampmIndex+aOffset]==ETokenPm && iDateTime.Hour()<12)
|
|
417 |
error=iDateTime.SetHour(iDateTime.Hour()+12);
|
|
418 |
if (error!=KErrNone)
|
|
419 |
return(error);
|
|
420 |
|
|
421 |
if (aOffset!=0)
|
|
422 |
return(ETimePresent|EDatePresent);
|
|
423 |
return(ETimePresent);
|
|
424 |
}
|
|
425 |
|
|
426 |
TInt TStringToDateTime::NextToken(TInt& aTokenLen)
|
|
427 |
{
|
|
428 |
if (iLex.Eos())
|
|
429 |
return ENullToken;
|
|
430 |
|
|
431 |
TChar ch=iLex.Peek();
|
|
432 |
|
|
433 |
if (ch.IsDigit())
|
|
434 |
{
|
|
435 |
iLex.Mark();
|
|
436 |
do iLex.Inc(); while (iLex.Peek().IsDigit());
|
|
437 |
|
|
438 |
TPtrC des=iLex.MarkedToken();
|
|
439 |
|
|
440 |
TInt digit;
|
|
441 |
TLex lex(des);
|
|
442 |
if (lex.Val(digit)!=KErrNone)
|
|
443 |
return(EErrorToken);
|
|
444 |
aTokenLen = des.Length();
|
|
445 |
return(digit);
|
|
446 |
}
|
|
447 |
else if (IsSeparator(ch))
|
|
448 |
{
|
|
449 |
iLex.Inc();
|
|
450 |
iLex.SkipSpace();
|
|
451 |
aTokenLen = 1;
|
|
452 |
return(GetSeparatorToken(ch));
|
|
453 |
}
|
|
454 |
else
|
|
455 |
{
|
|
456 |
iLex.Mark();
|
|
457 |
do iLex.Inc(); while (iLex.Peek().IsAlpha() || iLex.Peek().IsDigit());
|
|
458 |
|
|
459 |
TPtrC des=iLex.MarkedToken();
|
|
460 |
aTokenLen = des.Length();
|
|
461 |
|
|
462 |
for (TInt month=EJanuary; month<=EDecember; ++month)
|
|
463 |
{
|
|
464 |
// Abbreviated month name
|
|
465 |
TMonthNameAbb nameAbb((TMonth)month);
|
|
466 |
if (nameAbb.CompareF(des)==0)
|
|
467 |
return(-(month+1)); // All values negative
|
|
468 |
|
|
469 |
// Full month name
|
|
470 |
TMonthName name((TMonth)month);
|
|
471 |
if (name.CompareF(des)==0)
|
|
472 |
return(-(month+1)); // All values negative
|
|
473 |
}
|
|
474 |
|
|
475 |
// Substring of am or pm
|
|
476 |
TAmPmName am(EAm);
|
|
477 |
TAmPmName pm(EPm);
|
|
478 |
|
|
479 |
if (am.FindF(des)==0)
|
|
480 |
return(ETokenAm);
|
|
481 |
else if (pm.FindF(des)==0)
|
|
482 |
return(ETokenPm);
|
|
483 |
|
|
484 |
return(EErrorToken);
|
|
485 |
}
|
|
486 |
}
|
|
487 |
|
|
488 |
|
|
489 |
TInt TStringToDateTime::Parse(TTime& aTime)
|
|
490 |
{
|
|
491 |
|
|
492 |
iLex.SkipSpace();
|
|
493 |
TInt i = 0;
|
|
494 |
for (;;)
|
|
495 |
{
|
|
496 |
if (i==EMaxTokens-1) // space left to append NullToken
|
|
497 |
return KErrArgument;
|
|
498 |
TInt len;
|
|
499 |
TInt token=NextToken(len);// uses iLex
|
|
500 |
if (token==EErrorToken)
|
|
501 |
return KErrArgument;
|
|
502 |
if (token==ENullToken)
|
|
503 |
break;
|
|
504 |
iFormula[i]=token; // append token to formula
|
|
505 |
iTokenLen[i]=(TUint8)Min(len, 255);
|
|
506 |
++i;
|
|
507 |
}
|
|
508 |
iCount=i;
|
|
509 |
|
|
510 |
StripSpaceTokens();// Uses then resets iCount
|
|
511 |
TInt ret=CrackTokenFormula();
|
|
512 |
if (ret<0)
|
|
513 |
return(ret);
|
|
514 |
if (iDateTime.Year()>9999)
|
|
515 |
return KErrArgument;
|
|
516 |
aTime=iDateTime;
|
|
517 |
return(ret);
|
|
518 |
}
|
|
519 |
|
|
520 |
EXPORT_C TInt TTime::Parse(const TDesC& aDes,TInt aCenturyOffset)
|
|
521 |
/**
|
|
522 |
Parses a descriptor containing either or both a date and time, and sets this
|
|
523 |
TTime to the value of the parsed descriptor.
|
|
524 |
|
|
525 |
The descriptor may contain the date only, the time only, the date followed
|
|
526 |
by the time, or the time followed by the date. When both the date and time
|
|
527 |
are specified in the descriptor, they should be separated using one or more
|
|
528 |
space characters.
|
|
529 |
|
|
530 |
Leading zeros and spaces preceding any time or date components are discarded.
|
|
531 |
|
|
532 |
Dates may be specified either with all three components (day, month and year),
|
|
533 |
or with just two components; for example month and day. The date suffix ("st"
|
|
534 |
"nd" "rd" or "th") may not be included in the descriptor.
|
|
535 |
|
|
536 |
The date and its components may take different forms:
|
|
537 |
|
|
538 |
1. The month may be represented by text or by numbers.
|
|
539 |
|
|
540 |
2 European (DD/MM/YYYY), American (MM/DD/YYYY) and Japanese (YYYY/MM/DD) date
|
|
541 |
formats are supported. An exception to this ordering of date components occurs
|
|
542 |
when European or American formatting is used and the month is represented
|
|
543 |
by text. In this case, the month may be positioned in either the first or
|
|
544 |
second field. When using Japanese date format, the month, whether text or
|
|
545 |
numbers, must always be the second field.
|
|
546 |
|
|
547 |
3. The year may be two or four digits. When the year is a two digit number, (e.g.
|
|
548 |
97 rather than 1997), to resolve any confusion as to which century the year
|
|
549 |
falls in, the second argument determines the century. For example, if the
|
|
550 |
current year is 1997, a value for aCenturyOffset of 20 means that any two
|
|
551 |
digit year will resolve to a year in the range 1920 to 2019. In this case,
|
|
552 |
two digit years between 00 and 19 inclusive refer to the years between 2000
|
|
553 |
and 2019 and two digit years between 20 and 99 inclusive refer to the years
|
|
554 |
between 1920 and 1999. By default, two digit years are in the current century
|
|
555 |
(aCenturyOffset = 0).
|
|
556 |
|
|
557 |
4. Any of the following characters may be used as the date separator: /(slash)
|
|
558 |
- (dash) , (comma), spaces, or either of the date separator characters specified
|
|
559 |
in TLocale::SetDateSeparator() (at index 1 or 2). Other characters are illegal.
|
|
560 |
|
|
561 |
If a colon or a dot has been specified in TLocale as the date separator character,
|
|
562 |
neither may be used as date separators in this function.
|
|
563 |
|
|
564 |
If specified, the time must include the hour, but both minutes and seconds,
|
|
565 |
or seconds alone may be omitted.
|
|
566 |
|
|
567 |
The time and its components may take different forms:
|
|
568 |
|
|
569 |
1. An am/pm time suffix may be appended to the time. If 24 hour clock format
|
|
570 |
is in use, this text will be ignored.
|
|
571 |
|
|
572 |
2. The am/pm suffix may be abbreviated to "a" or "p".
|
|
573 |
|
|
574 |
3. Any of the following characters may be used as the time separator: :(colon)
|
|
575 |
.(dot) or either of the time separator characters specified in
|
|
576 |
TLocale::SetDateSeparator() (at index 1 or 2). Other characters are illegal.
|
|
577 |
|
|
578 |
When a character can be interpreted as either a date or time separator character,
|
|
579 |
this function will interpret it as a date separator.
|
|
580 |
|
|
581 |
Look out for cases in which wrongly interpreting the contents of a descriptor,
|
|
582 |
based on the interpretation of separator characters, causes an error. For
|
|
583 |
example, trying to interpret "5.6.1996" as a time is invalid and will return
|
|
584 |
an error of -2 because 1,996 seconds is out of range.
|
|
585 |
|
|
586 |
Notes:
|
|
587 |
|
|
588 |
1. The entire content of the descriptor must be valid and syntactically correct,
|
|
589 |
or an error will be returned and the parse will fail. So, excepting whitespace,
|
|
590 |
which is discarded, any trailing characters within the descriptor which do
|
|
591 |
not form part of the date or time are illegal.
|
|
592 |
|
|
593 |
2. If no time is specified in the descriptor, the hours, minutes and seconds
|
|
594 |
of this TTime are all set to zero, corresponding to midnight at the start
|
|
595 |
of the day specified in the date. If no date is specified, each of this TTime's
|
|
596 |
date components are set to zero.
|
|
597 |
|
|
598 |
@param aDes Descriptor containing any combination of date and
|
|
599 |
time as text.
|
|
600 |
@param aCenturyOffset Offset between zero (the default) and 99. Allows a flexible
|
|
601 |
interpretation of the century for two digit year values.
|
|
602 |
If less than zero, or greater than 99, a panic occurs.
|
|
603 |
|
|
604 |
@return If equal to or greater than zero, the function completed successfully.
|
|
605 |
EParseDatePresent and/or EParseTimePresent indicate whether either or both
|
|
606 |
of the date or time are present.
|
|
607 |
If less than zero, an error code.
|
|
608 |
KErrGeneral indicates that the time or date value is out of range,
|
|
609 |
e.g. if the hour is greater than 23 or if the minute is greater
|
|
610 |
than 59.
|
|
611 |
KErrNotSupported indicates that a two field date has been entered.
|
|
612 |
KErrArgument indicates that the descriptor was syntactically incorrect.
|
|
613 |
If the function fails, this TTime object remains unchanged.
|
|
614 |
*/
|
|
615 |
{
|
|
616 |
|
|
617 |
TStringToDateTime parse(aDes,aCenturyOffset);
|
|
618 |
return parse.Parse(*this);
|
|
619 |
}
|
|
620 |
|