os/ossrv/genericopenlibs/cstdlib/LTIME/TIME.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-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 "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 // Mapping between EPOC32 time and libc time
    15 // The basic philosophy is to work in time_t units (TInt) which
    16 // will be essentially TTimeIntervalSeconds from the start of Unix time.
    17 // To stay compliant with the C-Standard (with reference to C99 draft), we  
    18 // set the meaning of time_t to be Universal time.
    19 // 
    20 //
    21 
    22 #include <e32std.h>
    23 #include "LTIME.H"
    24 #include <sys/reent.h>	    // for _ASCTIME_SIZE
    25 #include <sys/time.h>	    // for gettimeofday
    26 #include <time.h>
    27 #include <string.h>	    // for strcpy
    28 
    29 #define UNIX_BASE   TTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000))    // 00:00, Jan 1st 1970
    30 
    31 // Utility routines for converting between representations
    32 
    33 static struct tm& as_struct_tm (const time_t& t, struct tm& res)
    34     {
    35     TTime us = UNIX_BASE + TTimeIntervalSeconds(t);
    36     TDateTime dt = us.DateTime();
    37 
    38     res.tm_sec  = dt.Second();
    39     res.tm_min  = dt.Minute();
    40     res.tm_hour = dt.Hour();
    41     res.tm_mday = dt.Day() + 1;
    42     res.tm_mon  = dt.Month();
    43     res.tm_year = dt.Year() - 1900;
    44 
    45     // EPOC32 counts the year day as Jan 1st == day 1
    46     res.tm_yday = us.DayNoInYear() - 1;
    47 
    48     // EPOC32 counts the weekdays from 0==Monday to 6==Sunday
    49     res.tm_wday = us.DayNoInWeek() + 1;
    50     if (res.tm_wday==7)
    51 	    res.tm_wday=0;	// Sunday==0 in a struct tm
    52 
    53     // newlib just sets this field to -1
    54     // tm_isdst doesn't really make sense here since we don't 
    55     // know the locale for which to interpret this time.
    56 
    57     res.tm_isdst = -1;
    58 
    59     return res;
    60     }
    61 
    62 static void as_ttime (const struct tm& p, TTime& res, TBool normalise=EFalse)
    63     {
    64     TDateTime dt;
    65     TInt err = dt.Set(p.tm_year+1900, (enum TMonth)p.tm_mon, p.tm_mday-1, 
    66 	p.tm_hour, p.tm_min, p.tm_sec, 0);
    67     if (err == KErrNone)
    68 	{
    69 	res = dt;
    70 	return;
    71 	}
    72     if (!normalise)
    73 	{
    74 	res = TInt64(-1);
    75 	return;
    76 	}
    77     // Try to normalise things (for mktime)
    78     dt.Set(p.tm_year+1900, EJanuary, 0, 0, 0, 0, 0);
    79     res = dt;
    80     res += TTimeIntervalMonths (p.tm_mon);
    81     res += TTimeIntervalDays   (p.tm_mday-1);
    82     res += TTimeIntervalHours  (p.tm_hour);
    83     res += TTimeIntervalMinutes(p.tm_min);
    84     res += TTimeIntervalSeconds(p.tm_sec);
    85     }
    86 
    87 inline void as_ttime (const time_t& p, TTime& res)
    88     {
    89     res = UNIX_BASE + TTimeIntervalSeconds(p);
    90     }
    91 
    92 GLDEF_C time_t as_time_t(const TTime& t)
    93     {
    94     TTimeIntervalSeconds res;
    95     TInt err = t.SecondsFrom(UNIX_BASE, res);
    96     if (err)
    97 	return -1;
    98     else
    99 	return res.Int();
   100     }
   101 
   102 // Utility routine for formatting a TTime into a descriptor using the
   103 // UNIX ctime format. NB. EPOC32 abbreviations can be up to KMaxDayNameAbb
   104 // and KMaxMonthNameAbb characters (both == 4). The %F is needed to
   105 // force the meanings of %D, %Y etc.
   106 
   107 static TDes8& as_string (TTime& t, TDes8& res)
   108     {
   109     // UNICODE problem - t.Format operates on TDes => TDes16
   110 
   111 #if !defined(_UNICODE)
   112     TRAPD(err, t.FormatL(res, _L("%F%*E %*N %D %H:%T:%S %Y")));
   113 #else
   114     TBuf<_ASCTIME_SIZE> unires;
   115     TRAPD(err, t.FormatL(unires, _L("%F%*E %*N %D %H:%T:%S %Y")));
   116     if (!err)
   117 	res.Copy(unires);
   118 #endif
   119     if (err)
   120 	res = _L8("Error\n");
   121     else
   122 	res.Append('\n');
   123     return res;
   124     }
   125 
   126 /**
   127 Intended Usage:	Utility routine for converting from UTC to localtime.
   128 @return   		Localtime in seconds
   129 @param 			aUniversalTime Universaltime in seconds
   130 */
   131 inline time_t toLocal (const time_t aUniversalTime)
   132     {
   133     TTimeIntervalSeconds offset = User::UTCOffset();
   134     return aUniversalTime + offset.Int();
   135     }
   136 
   137 /**
   138 Intended Usage:	Utility routine for converting from localtime to UTC.
   139 				However, having decided that time_t is always Universal time, toGMT is empty.
   140 @return			Localtime Universaltime in seconds
   141 @param 			aLocalTime Universaltime in seconds (meaning of time_t is UTC)
   142 */
   143 inline time_t toGMT (const time_t aLocalTime)
   144     {
   145     return aLocalTime;
   146     }
   147 
   148 // external interface for the C library
   149 
   150 extern "C" {
   151 /**
   152 Intended Usage:	Get current UTC time.
   153 				Get the number of seconds elapsed since 00:00 hours, 
   154 				Jan 1, 1970 UTC from the system clock.
   155 @return   		Elapsed time in seconds, as described.
   156 @param 			p Location where to store the retrieved value. 
   157 				If this is NULL the value is not stored. 
   158 				But it is still returned by the function.
   159 				time_t is generally defined by default to long.
   160 */
   161 EXPORT_C time_t time (time_t* p)
   162     {
   163     TTime t;
   164     t.UniversalTime();
   165 	
   166     time_t res = as_time_t(t);
   167     if (p)
   168 		*p = res;
   169     return res;
   170     }
   171 /**
   172 Intended Usage:	The gettimeofday function obtains the current UTC time, which is 
   173 				expressed as seconds and microseconds since 00:00:00 Coordinated Universal Time (UTC), 
   174 				January 1, 1970, and stores it in a timeval structure.
   175 				Please note that tz_minuteswest includes daytime saving. The struct member tz_dsttime is no 
   176 				longer supported by Symbian OS and therefore set to Zero.
   177 @publishedAll
   178 @released
   179 @return
   180 @param 			tp	Struct with two members of type long (tv_sec, tv_usec)
   181 @param 			tzp Struct with two members of type integer (tz_minuteswest, tz_dsttime)
   182 */
   183 EXPORT_C int gettimeofday (struct timeval *tp, struct timezone *tzp)
   184     {
   185     if (tp)
   186 	{
   187 	TTime t;
   188 	t.UniversalTime();
   189 	
   190 	TTimeIntervalSeconds sec;
   191 	TInt err = t.SecondsFrom(UNIX_BASE, sec);
   192 	if (err)
   193 	    return -1;
   194 	else
   195 	    tp->tv_sec = sec.Int();
   196 	t -= sec;
   197 	TTimeIntervalMicroSeconds usec = t.MicroSecondsFrom(UNIX_BASE);
   198 	TInt64 hackyfix = usec.Int64();	// because GetTInt() isn't declared const
   199 	tp->tv_usec = I64INT(hackyfix);
   200 	}
   201     if (tzp)
   202 	{
   203 	    tzp->tz_minuteswest = (User::UTCOffset().Int())/60;
   204 	    tzp->tz_dsttime = 0;
   205 	}
   206     return 0;
   207     }
   208 /**
   209 Return number of clock ticks since process start.
   210 Returns the number of clock ticks elapsed.
   211 A macro constant called CLK_TCK defines the relation betwen
   212 clock tick and second (clock ticks per second).
   213 @return   The number of clock ticks elapsed since start.
   214 clock_t type is defined by default as long int by most compilers.
   215 */
   216 EXPORT_C clock_t clock ()
   217     {
   218     return -1;
   219     }
   220 /**
   221 A reentrant version of gmtime(). 
   222 */
   223 EXPORT_C struct tm* gmtime_r (const time_t* p, struct tm* res)
   224     {
   225     return &as_struct_tm( toGMT(*p), *res);
   226     }
   227 /**
   228 A reentrant version of localtime().
   229 */
   230 EXPORT_C struct tm* localtime_r (const time_t* p, struct tm* res)
   231     {
   232     return &as_struct_tm( toLocal(*p), *res);
   233     }
   234 /**
   235 Convert tm structure to time_t value.
   236 Checks the members of the tm structure passed as parameter ptm 
   237 adjusting the values if the ones provided are not in the possible range 
   238 or they are not complete or mistaken and then translates that structure 
   239 to a time_t value (seconds elapsed since Jan 1, 1970) that is returned.
   240 The original values of tm_wday and tm_yday members of ptm are ignored 
   241 and filled with the correspondent ones to the calculated date. 
   242 The range of tm_mday is not checked until tm_mon and tm_year are determined.
   243 @return A time_t value corresponding to the date and time passed in ptm parameter.
   244 On error, a -1 value is returned.
   245 @param p Pointer to a tm structure, that contains data to be computed.
   246 */
   247 EXPORT_C time_t mktime (struct tm *p)
   248     {
   249     TTime t;
   250     as_ttime(*p, t, ETrue);
   251     time_t res = as_time_t(t);
   252 
   253     as_struct_tm(res, *p);    // Must also update the struct tm passed to us...
   254     return res;
   255     }
   256 
   257 /**
   258 A reentrant version of asctime().
   259 */
   260 EXPORT_C char* asctime_r (const struct tm *p, char* result)
   261     {
   262     TTime t;
   263     as_ttime(*p, t);
   264 
   265     TPtr8 rDes((TUint8*)result, _ASCTIME_SIZE);
   266 
   267     return (char *)as_string(t, rDes).PtrZ();
   268     }
   269 
   270 /**
   271 A reentrant version of ctime().
   272 */
   273 EXPORT_C char* ctime_r (const time_t* p, char* result)
   274     {
   275     TTime t;
   276     as_ttime(toLocal(*p), t);
   277 
   278     TPtr8 rDes((TUint8*)result, _ASCTIME_SIZE);
   279 
   280     return (char *)as_string(t, rDes).PtrZ();
   281     }
   282 
   283 } // extern "C"