os/kernelhwsrv/kernel/eka/euser/us_parse.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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