diff -r c55016431358 -r 0a7b44b10206 symport/e32/euser/us_parse.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32/euser/us_parse.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,620 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\euser\us_parse.cpp +// +// + +#include "us_std.h" + +class TStringToDateTime + { +public: + TStringToDateTime(const TDesC& aDes,TInt aCenturyOffset); + TInt Parse(TTime& aTime); + enum {ETimePresent=1,EDatePresent}; +private: +// tokens + enum {EDec=-12,ENov,EOct,ESep,EAug,EJul,EJun,EMay,EApr,EMar,EFeb,EJan}; + enum {ETokenAm=-19,ETokenPm}; + enum TDateSeparators{ESlash=-39,EDash,EComma,ESpace,EDateLocale1,EDateLocale2}; + enum TTimeSeparators{EColon=-49,EDot,ETimeLocale1,ETimeLocale2}; + enum TDecimalSeparators{EDecimalLocale=-59}; + enum {EErrorToken=-99,ENullToken=-100}; +// + enum {ENumberOfDateSep=6,ENumberOfTimeSep=4,EMaxTokens=27}; + enum {EFirstDateSep=ESlash,ELastDateSep=EDateLocale2,EFirstTimeSep=EColon,ELastTimeSep=ETimeLocale2}; +private: + TInt NextToken(TInt& aTokenLen); + void StripSpaceTokens(); + TInt CrackTokenFormula(); + TInt GetDate(TInt aFormulaPos,TInt& aTokenCount); + TInt GetTime(TInt aFormulaPos,TInt& aTokenCount); +// + TInt GetSeparatorToken(TChar aChar) const; + TBool IsTimeSeparator(TChar aChar) const; + TBool IsDateSeparator(TChar aChar) const; + TBool IsDecimalSeparator(TChar aChar) const; + TBool IsSeparator(TChar aChar) const; + TBool IsSeparator(TInt aToken) const; + inline TBool IsTimeSeparator(TInt aToken) const; + inline TBool IsDateSeparator(TInt aToken) const; + TBool IsDecimalSeparator(TInt aToken) const; + inline TBool IsAmPm(TInt aToken) const; + inline TBool IsAlphaMonth(TInt aToken) const; +private: + TLex iLex; + TInt iCenturyOffset; + TDateFormat iDateFormat; + TChar iTimeSepChars[ENumberOfTimeSep]; + TChar iDateSepChars[ENumberOfDateSep]; + TChar iDecSepChar; + TDateTime iDateTime; + TInt iCount; + TInt iFormula[EMaxTokens];// 27 max possible with valid des (including spaces):" 10 : 00 : 00 . 000000 pm 6 / 12 / 99 " + TUint8 iTokenLen[EMaxTokens]; + }; + +inline TBool TStringToDateTime::IsTimeSeparator(TInt aToken) const + { + return(aToken >= EFirstTimeSep && aToken <=ELastTimeSep); + } +inline TBool TStringToDateTime::IsDateSeparator(TInt aToken) const + { + return(aToken>=EFirstDateSep && aToken<=ELastDateSep); + } +inline TBool TStringToDateTime::IsAmPm(TInt aToken) const + { + return(aToken==ETokenAm || aToken==ETokenPm); + } +inline TBool TStringToDateTime::IsAlphaMonth(TInt aToken) const + { + return (aToken>=EDec && aToken<=EJan); + } + +inline TBool TStringToDateTime::IsDecimalSeparator(TChar aChar) const + { + return(aChar==iDecSepChar); + } +inline TBool TStringToDateTime::IsDecimalSeparator(TInt aToken) const + { + return(aToken==EDecimalLocale); + } + +TStringToDateTime::TStringToDateTime(const TDesC& aDes,TInt aCenturyOffset) + : iLex(aDes),iCenturyOffset(aCenturyOffset),iDateTime(0,EJanuary,0,0,0,0,0) + { + + __ASSERT_ALWAYS(aCenturyOffset>=0 && aCenturyOffset<100,Panic(ETTimeValueOutOfRange)); + TLocale locale; + iDateFormat=locale.DateFormat(); + + iTimeSepChars[0]=':'; + iTimeSepChars[1]='.'; + iTimeSepChars[2]=locale.TimeSeparator(1); + iTimeSepChars[3]=locale.TimeSeparator(2); + + iDateSepChars[0]='/'; + iDateSepChars[1]='-'; + iDateSepChars[2]=','; + iDateSepChars[3]=' '; + iDateSepChars[4]=locale.DateSeparator(1); + iDateSepChars[5]=locale.DateSeparator(2); + iDecSepChar = locale.DecimalSeparator(); + } + +TBool TStringToDateTime::IsTimeSeparator(TChar aChar) const + { + + for (TInt ii=0;ii=iCenturyOffset) + { + if (year>=00 && year=00 && year00 hrs. Ignore 13am + else if (iFormula[ampmIndex+aOffset]==ETokenPm && iDateTime.Hour()<12) + error=iDateTime.SetHour(iDateTime.Hour()+12); + if (error!=KErrNone) + return(error); + + if (aOffset!=0) + return(ETimePresent|EDatePresent); + return(ETimePresent); + } + +TInt TStringToDateTime::NextToken(TInt& aTokenLen) + { + if (iLex.Eos()) + return ENullToken; + + TChar ch=iLex.Peek(); + + if (ch.IsDigit()) + { + iLex.Mark(); + do iLex.Inc(); while (iLex.Peek().IsDigit()); + + TPtrC des=iLex.MarkedToken(); + + TInt digit; + TLex lex(des); + if (lex.Val(digit)!=KErrNone) + return(EErrorToken); + aTokenLen = des.Length(); + return(digit); + } + else if (IsSeparator(ch)) + { + iLex.Inc(); + iLex.SkipSpace(); + aTokenLen = 1; + return(GetSeparatorToken(ch)); + } + else + { + iLex.Mark(); + do iLex.Inc(); while (iLex.Peek().IsAlpha() || iLex.Peek().IsDigit()); + + TPtrC des=iLex.MarkedToken(); + aTokenLen = des.Length(); + + for (TInt month=EJanuary; month<=EDecember; ++month) + { + // Abbreviated month name + TMonthNameAbb nameAbb((TMonth)month); + if (nameAbb.CompareF(des)==0) + return(-(month+1)); // All values negative + + // Full month name + TMonthName name((TMonth)month); + if (name.CompareF(des)==0) + return(-(month+1)); // All values negative + } + + // Substring of am or pm + TAmPmName am(EAm); + TAmPmName pm(EPm); + + if (am.FindF(des)==0) + return(ETokenAm); + else if (pm.FindF(des)==0) + return(ETokenPm); + + return(EErrorToken); + } + } + + +TInt TStringToDateTime::Parse(TTime& aTime) + { + + iLex.SkipSpace(); + TInt i = 0; + for (;;) + { + if (i==EMaxTokens-1) // space left to append NullToken + return KErrArgument; + TInt len; + TInt token=NextToken(len);// uses iLex + if (token==EErrorToken) + return KErrArgument; + if (token==ENullToken) + break; + iFormula[i]=token; // append token to formula + iTokenLen[i]=(TUint8)Min(len, 255); + ++i; + } + iCount=i; + + StripSpaceTokens();// Uses then resets iCount + TInt ret=CrackTokenFormula(); + if (ret<0) + return(ret); + if (iDateTime.Year()>9999) + return KErrArgument; + aTime=iDateTime; + return(ret); + } + +EXPORT_C TInt TTime::Parse(const TDesC& aDes,TInt aCenturyOffset) +/** +Parses a descriptor containing either or both a date and time, and sets this +TTime to the value of the parsed descriptor. + +The descriptor may contain the date only, the time only, the date followed +by the time, or the time followed by the date. When both the date and time +are specified in the descriptor, they should be separated using one or more +space characters. + +Leading zeros and spaces preceding any time or date components are discarded. + +Dates may be specified either with all three components (day, month and year), +or with just two components; for example month and day. The date suffix ("st" +"nd" "rd" or "th") may not be included in the descriptor. + +The date and its components may take different forms: + +1. The month may be represented by text or by numbers. + +2 European (DD/MM/YYYY), American (MM/DD/YYYY) and Japanese (YYYY/MM/DD) date + formats are supported. An exception to this ordering of date components occurs + when European or American formatting is used and the month is represented + by text. In this case, the month may be positioned in either the first or + second field. When using Japanese date format, the month, whether text or + numbers, must always be the second field. + +3. The year may be two or four digits. When the year is a two digit number, (e.g. + 97 rather than 1997), to resolve any confusion as to which century the year + falls in, the second argument determines the century. For example, if the + current year is 1997, a value for aCenturyOffset of 20 means that any two + digit year will resolve to a year in the range 1920 to 2019. In this case, + two digit years between 00 and 19 inclusive refer to the years between 2000 + and 2019 and two digit years between 20 and 99 inclusive refer to the years + between 1920 and 1999. By default, two digit years are in the current century + (aCenturyOffset = 0). + +4. Any of the following characters may be used as the date separator: /(slash) + - (dash) , (comma), spaces, or either of the date separator characters specified + in TLocale::SetDateSeparator() (at index 1 or 2). Other characters are illegal. + +If a colon or a dot has been specified in TLocale as the date separator character, +neither may be used as date separators in this function. + +If specified, the time must include the hour, but both minutes and seconds, +or seconds alone may be omitted. + +The time and its components may take different forms: + +1. An am/pm time suffix may be appended to the time. If 24 hour clock format + is in use, this text will be ignored. + +2. The am/pm suffix may be abbreviated to "a" or "p". + +3. Any of the following characters may be used as the time separator: :(colon) + .(dot) or either of the time separator characters specified in + TLocale::SetDateSeparator() (at index 1 or 2). Other characters are illegal. + +When a character can be interpreted as either a date or time separator character, +this function will interpret it as a date separator. + +Look out for cases in which wrongly interpreting the contents of a descriptor, +based on the interpretation of separator characters, causes an error. For +example, trying to interpret "5.6.1996" as a time is invalid and will return +an error of -2 because 1,996 seconds is out of range. + +Notes: + +1. The entire content of the descriptor must be valid and syntactically correct, + or an error will be returned and the parse will fail. So, excepting whitespace, + which is discarded, any trailing characters within the descriptor which do + not form part of the date or time are illegal. + +2. If no time is specified in the descriptor, the hours, minutes and seconds + of this TTime are all set to zero, corresponding to midnight at the start + of the day specified in the date. If no date is specified, each of this TTime's + date components are set to zero. + +@param aDes Descriptor containing any combination of date and + time as text. +@param aCenturyOffset Offset between zero (the default) and 99. Allows a flexible + interpretation of the century for two digit year values. + If less than zero, or greater than 99, a panic occurs. + +@return If equal to or greater than zero, the function completed successfully. + EParseDatePresent and/or EParseTimePresent indicate whether either or both + of the date or time are present. + If less than zero, an error code. + KErrGeneral indicates that the time or date value is out of range, + e.g. if the hour is greater than 23 or if the minute is greater + than 59. + KErrNotSupported indicates that a two field date has been entered. + KErrArgument indicates that the descriptor was syntactically incorrect. + If the function fails, this TTime object remains unchanged. +*/ + { + + TStringToDateTime parse(aDes,aCenturyOffset); + return parse.Parse(*this); + } +