1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LTIME/TIME.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,283 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Mapping between EPOC32 time and libc time
1.18 +// The basic philosophy is to work in time_t units (TInt) which
1.19 +// will be essentially TTimeIntervalSeconds from the start of Unix time.
1.20 +// To stay compliant with the C-Standard (with reference to C99 draft), we
1.21 +// set the meaning of time_t to be Universal time.
1.22 +//
1.23 +//
1.24 +
1.25 +#include <e32std.h>
1.26 +#include "LTIME.H"
1.27 +#include <sys/reent.h> // for _ASCTIME_SIZE
1.28 +#include <sys/time.h> // for gettimeofday
1.29 +#include <time.h>
1.30 +#include <string.h> // for strcpy
1.31 +
1.32 +#define UNIX_BASE TTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000)) // 00:00, Jan 1st 1970
1.33 +
1.34 +// Utility routines for converting between representations
1.35 +
1.36 +static struct tm& as_struct_tm (const time_t& t, struct tm& res)
1.37 + {
1.38 + TTime us = UNIX_BASE + TTimeIntervalSeconds(t);
1.39 + TDateTime dt = us.DateTime();
1.40 +
1.41 + res.tm_sec = dt.Second();
1.42 + res.tm_min = dt.Minute();
1.43 + res.tm_hour = dt.Hour();
1.44 + res.tm_mday = dt.Day() + 1;
1.45 + res.tm_mon = dt.Month();
1.46 + res.tm_year = dt.Year() - 1900;
1.47 +
1.48 + // EPOC32 counts the year day as Jan 1st == day 1
1.49 + res.tm_yday = us.DayNoInYear() - 1;
1.50 +
1.51 + // EPOC32 counts the weekdays from 0==Monday to 6==Sunday
1.52 + res.tm_wday = us.DayNoInWeek() + 1;
1.53 + if (res.tm_wday==7)
1.54 + res.tm_wday=0; // Sunday==0 in a struct tm
1.55 +
1.56 + // newlib just sets this field to -1
1.57 + // tm_isdst doesn't really make sense here since we don't
1.58 + // know the locale for which to interpret this time.
1.59 +
1.60 + res.tm_isdst = -1;
1.61 +
1.62 + return res;
1.63 + }
1.64 +
1.65 +static void as_ttime (const struct tm& p, TTime& res, TBool normalise=EFalse)
1.66 + {
1.67 + TDateTime dt;
1.68 + TInt err = dt.Set(p.tm_year+1900, (enum TMonth)p.tm_mon, p.tm_mday-1,
1.69 + p.tm_hour, p.tm_min, p.tm_sec, 0);
1.70 + if (err == KErrNone)
1.71 + {
1.72 + res = dt;
1.73 + return;
1.74 + }
1.75 + if (!normalise)
1.76 + {
1.77 + res = TInt64(-1);
1.78 + return;
1.79 + }
1.80 + // Try to normalise things (for mktime)
1.81 + dt.Set(p.tm_year+1900, EJanuary, 0, 0, 0, 0, 0);
1.82 + res = dt;
1.83 + res += TTimeIntervalMonths (p.tm_mon);
1.84 + res += TTimeIntervalDays (p.tm_mday-1);
1.85 + res += TTimeIntervalHours (p.tm_hour);
1.86 + res += TTimeIntervalMinutes(p.tm_min);
1.87 + res += TTimeIntervalSeconds(p.tm_sec);
1.88 + }
1.89 +
1.90 +inline void as_ttime (const time_t& p, TTime& res)
1.91 + {
1.92 + res = UNIX_BASE + TTimeIntervalSeconds(p);
1.93 + }
1.94 +
1.95 +GLDEF_C time_t as_time_t(const TTime& t)
1.96 + {
1.97 + TTimeIntervalSeconds res;
1.98 + TInt err = t.SecondsFrom(UNIX_BASE, res);
1.99 + if (err)
1.100 + return -1;
1.101 + else
1.102 + return res.Int();
1.103 + }
1.104 +
1.105 +// Utility routine for formatting a TTime into a descriptor using the
1.106 +// UNIX ctime format. NB. EPOC32 abbreviations can be up to KMaxDayNameAbb
1.107 +// and KMaxMonthNameAbb characters (both == 4). The %F is needed to
1.108 +// force the meanings of %D, %Y etc.
1.109 +
1.110 +static TDes8& as_string (TTime& t, TDes8& res)
1.111 + {
1.112 + // UNICODE problem - t.Format operates on TDes => TDes16
1.113 +
1.114 +#if !defined(_UNICODE)
1.115 + TRAPD(err, t.FormatL(res, _L("%F%*E %*N %D %H:%T:%S %Y")));
1.116 +#else
1.117 + TBuf<_ASCTIME_SIZE> unires;
1.118 + TRAPD(err, t.FormatL(unires, _L("%F%*E %*N %D %H:%T:%S %Y")));
1.119 + if (!err)
1.120 + res.Copy(unires);
1.121 +#endif
1.122 + if (err)
1.123 + res = _L8("Error\n");
1.124 + else
1.125 + res.Append('\n');
1.126 + return res;
1.127 + }
1.128 +
1.129 +/**
1.130 +Intended Usage: Utility routine for converting from UTC to localtime.
1.131 +@return Localtime in seconds
1.132 +@param aUniversalTime Universaltime in seconds
1.133 +*/
1.134 +inline time_t toLocal (const time_t aUniversalTime)
1.135 + {
1.136 + TTimeIntervalSeconds offset = User::UTCOffset();
1.137 + return aUniversalTime + offset.Int();
1.138 + }
1.139 +
1.140 +/**
1.141 +Intended Usage: Utility routine for converting from localtime to UTC.
1.142 + However, having decided that time_t is always Universal time, toGMT is empty.
1.143 +@return Localtime Universaltime in seconds
1.144 +@param aLocalTime Universaltime in seconds (meaning of time_t is UTC)
1.145 +*/
1.146 +inline time_t toGMT (const time_t aLocalTime)
1.147 + {
1.148 + return aLocalTime;
1.149 + }
1.150 +
1.151 +// external interface for the C library
1.152 +
1.153 +extern "C" {
1.154 +/**
1.155 +Intended Usage: Get current UTC time.
1.156 + Get the number of seconds elapsed since 00:00 hours,
1.157 + Jan 1, 1970 UTC from the system clock.
1.158 +@return Elapsed time in seconds, as described.
1.159 +@param p Location where to store the retrieved value.
1.160 + If this is NULL the value is not stored.
1.161 + But it is still returned by the function.
1.162 + time_t is generally defined by default to long.
1.163 +*/
1.164 +EXPORT_C time_t time (time_t* p)
1.165 + {
1.166 + TTime t;
1.167 + t.UniversalTime();
1.168 +
1.169 + time_t res = as_time_t(t);
1.170 + if (p)
1.171 + *p = res;
1.172 + return res;
1.173 + }
1.174 +/**
1.175 +Intended Usage: The gettimeofday function obtains the current UTC time, which is
1.176 + expressed as seconds and microseconds since 00:00:00 Coordinated Universal Time (UTC),
1.177 + January 1, 1970, and stores it in a timeval structure.
1.178 + Please note that tz_minuteswest includes daytime saving. The struct member tz_dsttime is no
1.179 + longer supported by Symbian OS and therefore set to Zero.
1.180 +@publishedAll
1.181 +@released
1.182 +@return
1.183 +@param tp Struct with two members of type long (tv_sec, tv_usec)
1.184 +@param tzp Struct with two members of type integer (tz_minuteswest, tz_dsttime)
1.185 +*/
1.186 +EXPORT_C int gettimeofday (struct timeval *tp, struct timezone *tzp)
1.187 + {
1.188 + if (tp)
1.189 + {
1.190 + TTime t;
1.191 + t.UniversalTime();
1.192 +
1.193 + TTimeIntervalSeconds sec;
1.194 + TInt err = t.SecondsFrom(UNIX_BASE, sec);
1.195 + if (err)
1.196 + return -1;
1.197 + else
1.198 + tp->tv_sec = sec.Int();
1.199 + t -= sec;
1.200 + TTimeIntervalMicroSeconds usec = t.MicroSecondsFrom(UNIX_BASE);
1.201 + TInt64 hackyfix = usec.Int64(); // because GetTInt() isn't declared const
1.202 + tp->tv_usec = I64INT(hackyfix);
1.203 + }
1.204 + if (tzp)
1.205 + {
1.206 + tzp->tz_minuteswest = (User::UTCOffset().Int())/60;
1.207 + tzp->tz_dsttime = 0;
1.208 + }
1.209 + return 0;
1.210 + }
1.211 +/**
1.212 +Return number of clock ticks since process start.
1.213 +Returns the number of clock ticks elapsed.
1.214 +A macro constant called CLK_TCK defines the relation betwen
1.215 +clock tick and second (clock ticks per second).
1.216 +@return The number of clock ticks elapsed since start.
1.217 +clock_t type is defined by default as long int by most compilers.
1.218 +*/
1.219 +EXPORT_C clock_t clock ()
1.220 + {
1.221 + return -1;
1.222 + }
1.223 +/**
1.224 +A reentrant version of gmtime().
1.225 +*/
1.226 +EXPORT_C struct tm* gmtime_r (const time_t* p, struct tm* res)
1.227 + {
1.228 + return &as_struct_tm( toGMT(*p), *res);
1.229 + }
1.230 +/**
1.231 +A reentrant version of localtime().
1.232 +*/
1.233 +EXPORT_C struct tm* localtime_r (const time_t* p, struct tm* res)
1.234 + {
1.235 + return &as_struct_tm( toLocal(*p), *res);
1.236 + }
1.237 +/**
1.238 +Convert tm structure to time_t value.
1.239 +Checks the members of the tm structure passed as parameter ptm
1.240 +adjusting the values if the ones provided are not in the possible range
1.241 +or they are not complete or mistaken and then translates that structure
1.242 +to a time_t value (seconds elapsed since Jan 1, 1970) that is returned.
1.243 +The original values of tm_wday and tm_yday members of ptm are ignored
1.244 +and filled with the correspondent ones to the calculated date.
1.245 +The range of tm_mday is not checked until tm_mon and tm_year are determined.
1.246 +@return A time_t value corresponding to the date and time passed in ptm parameter.
1.247 +On error, a -1 value is returned.
1.248 +@param p Pointer to a tm structure, that contains data to be computed.
1.249 +*/
1.250 +EXPORT_C time_t mktime (struct tm *p)
1.251 + {
1.252 + TTime t;
1.253 + as_ttime(*p, t, ETrue);
1.254 + time_t res = as_time_t(t);
1.255 +
1.256 + as_struct_tm(res, *p); // Must also update the struct tm passed to us...
1.257 + return res;
1.258 + }
1.259 +
1.260 +/**
1.261 +A reentrant version of asctime().
1.262 +*/
1.263 +EXPORT_C char* asctime_r (const struct tm *p, char* result)
1.264 + {
1.265 + TTime t;
1.266 + as_ttime(*p, t);
1.267 +
1.268 + TPtr8 rDes((TUint8*)result, _ASCTIME_SIZE);
1.269 +
1.270 + return (char *)as_string(t, rDes).PtrZ();
1.271 + }
1.272 +
1.273 +/**
1.274 +A reentrant version of ctime().
1.275 +*/
1.276 +EXPORT_C char* ctime_r (const time_t* p, char* result)
1.277 + {
1.278 + TTime t;
1.279 + as_ttime(toLocal(*p), t);
1.280 +
1.281 + TPtr8 rDes((TUint8*)result, _ASCTIME_SIZE);
1.282 +
1.283 + return (char *)as_string(t, rDes).PtrZ();
1.284 + }
1.285 +
1.286 +} // extern "C"