symport/e32/euser/us_parse.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     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 "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-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