Initial git commit -- Transition from CodeGuard repository
[sdk] / ecere / src / sys / Time.ec
1 namespace sys;
2
3 import "instance"
4
5 #define Date _Date
6 #define uint _uint
7 #define Method _Method
8 #define FileName _FileName
9 #define Instance _Instance
10 #define Size _Size
11 #define File _File
12 #define byte _byte
13 #define int64 _int64
14 #define uint64 _uint64
15 #define Alignment _Alignment
16
17 #if defined(__WIN32__)
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #include <mmsystem.h>
21 #elif defined(__unix__) || defined(__APPLE__)
22 #include <sys/time.h>
23 #include <sched.h>
24 #include <unistd.h>
25 #endif
26 #include <time.h>
27 #include <stdlib.h>
28
29 #undef uint
30 #undef int64
31 #undef uint64
32 #undef byte
33 #undef Method
34 #undef Alignment
35 #undef FileName
36 #undef Instance
37 #undef File
38 #undef Size
39 #undef Date
40
41 define EPOCH_YEAR      = 1970;
42 define EPOCH_WEEKDAY   = thursday;
43 static define SECS_PER_HOUR   = 60 * 60;
44 static define SECS_PER_DAY    = SECS_PER_HOUR * 24;
45
46 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
47 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
48 #define ISLEAP(y) (!((y)%4) && (((y) % 100) || (!((y)% 400))))
49
50 const int daysInAYearBeforeMonth[2][13] =
51 {
52    // Normal years.
53    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
54    // Leap years.
55    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
56 };
57
58 int monthLengths[2][12] =
59 {
60         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
61         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
62 };
63
64 char daysNames[7][4] =
65 {
66    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
67 };
68 char monthsNames[12][4] = 
69 {
70    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
71 };
72
73 #if defined(__WIN32__)
74
75 #define LL2FILETIME( ll, pft )   (pft)->dwLowDateTime = (UINT)(ll); (pft)->dwHighDateTime = (UINT)((ll) >> 32);
76 #define FILETIME2LL( pft, ll)    ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
77
78 static int TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
79 {
80    int limit_day, dayinsecs;
81
82    if(date->wMonth < compareDate->wMonth) return -1;
83    if(date->wMonth > compareDate->wMonth) return 1;
84
85    if(compareDate->wDayOfWeek <= 6)
86    {
87       WORD First;
88       int weekofmonth = compareDate->wDay;
89       First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay ) % 7 + 1;
90       limit_day = First + 7 * (weekofmonth - 1);
91       if(limit_day > monthLengths[date->wMonth==2 && ISLEAP(date->wYear)][date->wMonth - 1])
92          limit_day -= 7;
93    }
94    else
95    {
96       limit_day = compareDate->wDay;
97    }
98
99    limit_day = ((limit_day * 24  + compareDate->wHour) * 60 + compareDate->wMinute ) * 60;
100    dayinsecs = ((date->wDay * 24  + date->wHour) * 60 + date->wMinute ) * 60 + date->wSecond;
101    return dayinsecs < limit_day ? -1 : dayinsecs > limit_day ? 1 : 0;
102 }
103
104 static uint TIME_CompTimeZoneID(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, bool islocal)
105 {
106    int ret;
107    bool beforeStandardDate, afterDaylightDate;
108    DWORD retval = TIME_ZONE_ID_INVALID;
109    LONGLONG llTime = 0;
110    SYSTEMTIME SysTime;
111    FILETIME ftTemp;
112
113    if (pTZinfo->DaylightDate.wMonth != 0)
114    {
115       if (pTZinfo->StandardDate.wMonth == 0 ||
116          pTZinfo->StandardDate.wDay<1 ||
117          pTZinfo->StandardDate.wDay>5 ||
118          pTZinfo->DaylightDate.wDay<1 ||
119          pTZinfo->DaylightDate.wDay>5)
120       {
121          SetLastError(ERROR_INVALID_PARAMETER);
122          return TIME_ZONE_ID_INVALID;
123       }
124
125       if (!islocal)
126       {
127          FILETIME2LL( lpFileTime, llTime );
128          llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias ) * (LONGLONG)600000000;
129          LL2FILETIME( llTime, &ftTemp)
130          lpFileTime = &ftTemp;
131       }
132
133       FileTimeToSystemTime(lpFileTime, &SysTime);
134
135       ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
136       if (ret == -2)
137          return TIME_ZONE_ID_INVALID;
138
139       beforeStandardDate = ret < 0;
140
141       if (!islocal)
142       {
143          llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias ) * (LONGLONG)600000000;
144          LL2FILETIME( llTime, &ftTemp)
145          FileTimeToSystemTime(lpFileTime, &SysTime);
146       }
147
148       ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
149       if (ret == -2)
150        return TIME_ZONE_ID_INVALID;
151
152       afterDaylightDate = ret >= 0;
153
154       retval = TIME_ZONE_ID_STANDARD;
155       if( pTZinfo->DaylightDate.wMonth <  pTZinfo->StandardDate.wMonth )
156       {
157          if( beforeStandardDate && afterDaylightDate )
158              retval = TIME_ZONE_ID_DAYLIGHT;
159       }
160       else if( beforeStandardDate || afterDaylightDate )
161          retval = TIME_ZONE_ID_DAYLIGHT;
162    }
163    else 
164       retval = TIME_ZONE_ID_UNKNOWN;
165    return retval;
166 }
167
168 static bool TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, bool islocal, LONG *pBias)
169 {
170    LONG bias = pTZinfo->Bias;
171    DWORD tzid = TIME_CompTimeZoneID( pTZinfo, lpFileTime, islocal);
172
173    if( tzid == TIME_ZONE_ID_INVALID)
174       return false;
175    if (tzid == TIME_ZONE_ID_DAYLIGHT)
176       bias += pTZinfo->DaylightBias;
177    else if (tzid == TIME_ZONE_ID_STANDARD)
178       bias += pTZinfo->StandardBias;
179    *pBias = bias;
180    return true;
181 }
182
183 static bool _TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime)       
184 {
185    FILETIME ft;
186    LONG lBias;
187    LONGLONG t;
188    TIME_ZONE_INFORMATION tzinfo;
189
190    if(lpTimeZoneInformation)
191    {
192       memcpy(&tzinfo, lpTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
193    }
194    else
195    {
196       if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
197          return false;
198    }
199
200    if (!SystemTimeToFileTime(lpLocalTime, &ft))
201       return false;
202    FILETIME2LL( &ft, t)
203    if (!TIME_GetTimezoneBias(&tzinfo, &ft, true, &lBias))
204       return false;
205
206    t += (LONGLONG)lBias * 600000000;
207    LL2FILETIME( t, &ft)
208    return (bool)FileTimeToSystemTime(&ft, lpUniversalTime);
209 }
210 #endif
211
212 import "System"
213
214 public class Time : double
215 {
216    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
217    {
218       Time time = this;
219       int value;
220       char temp[256];
221       tempString[0] = 0;
222       value = (int)(time / (60 * 60 * 24));
223       if(value)
224       {
225          
226          sprintf(temp, "%d:", value);
227          strcat(tempString, temp);
228          time -= value * 60 * 60 * 24;
229       }
230       value = (int)(time / (60 * 60));
231       if(value)
232       {
233          sprintf(temp, "%d:", value);
234          strcat(tempString, temp);
235          time -= value * 60 * 60;
236       }
237
238       value = (int)(time / 60);
239       sprintf(temp, "%d:", value);
240       strcat(tempString, temp);
241       time -= value * 60;
242
243       value = (int)(time);
244       sprintf(temp, "%02d", value);
245       strcat(tempString, temp);
246       time -= value;
247
248       /*if(time > 0.00001)
249       {
250          sprintf(temp, "%f" time);
251          strcat(tempString, temp+1);
252       }*/
253       return tempString;
254    }
255 }
256
257 public class Seconds : Time { public property Time {} };
258
259 #if !defined(__WIN32__)
260 static time_t MakeTimeT(SecSince1970 t)
261 {
262    struct tm tm;
263    time_t result;
264    DateTime dt = t;
265    tm.tm_year = dt.year - 1900;
266    tm.tm_mon = dt.month;
267    tm.tm_mday = dt.day;
268    tm.tm_hour = dt.hour;
269    tm.tm_min = dt.minute;
270    tm.tm_sec = dt.second;
271    tm.tm_yday = dt.dayInTheYear;
272    tm.tm_wday = dt.dayOfTheWeek;
273    result = mktime(&tm);
274    return result;
275 }
276
277 static time_t MakeTimeTfromDT(DateTime dt)
278 {
279    struct tm tm;
280    time_t result;
281    tm.tm_year = dt.year - 1900;
282    tm.tm_mon = dt.month;
283    tm.tm_mday = dt.day;
284    tm.tm_hour = dt.hour;
285    tm.tm_min = dt.minute;
286    tm.tm_sec = dt.second;
287    tm.tm_yday = dt.dayInTheYear;
288    tm.tm_wday = dt.dayOfTheWeek;
289    result = mktime(&tm);
290    return result;
291 }
292
293 #endif
294
295 public class SecSince1970 : int64
296 {
297    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
298    {
299       if(this || !this)
300       {
301          // TOFIX:  passing argument 2 of '__ecereProp___ecereNameSpace__ecere__sys__DateTime_Set___ecereNameSpace__ecere__sys__SecSince1970' makes integer from pointer without a cast
302          DateTime t = this;
303          return t.OnGetString(tempString, fieldData, needClass);
304          // TOFIX:
305          // return ((DateTime)this).OnGetString(tempString, fieldData, needClass);
306       }
307       return tempString;
308    }
309
310    // Is this required?
311    int OnCompare(SecSince1970 data2)
312    {
313       int result = 0;
314       if(this && data2)
315       {
316          if(this > data2)
317             result = 1;
318          else if(this < data2)
319             result = -1;
320       }
321       return result;
322    }
323 public:
324    property SecSince1970 global
325    {
326       // TOFIX: 'return' with a value, in function returning void
327       set { return value.local; }
328       get
329       {
330       #if defined(__WIN32__)
331          SYSTEMTIME localTime, systemTime;
332          FILETIME fileTime, localFileTime;
333          DateTime input, global;
334
335          input = this;
336
337          localTime.wYear = (short)input.year;
338          localTime.wMonth = (short)input.month + 1;
339          localTime.wDay = (short)input.day;
340          localTime.wHour = (short)input.hour;
341          localTime.wMinute = (short)input.minute;
342          localTime.wSecond = (short)input.second;
343          localTime.wMilliseconds = 0;
344
345          /*
346          SystemTimeToFileTime(&localTime, &fileTime);
347          LocalFileTimeToFileTime(&fileTime, &localFileTime);
348          FileTimeToSystemTime(&localFileTime, &systemTime);
349          */
350
351          _TzSpecificLocalTimeToSystemTime(null, &localTime, &systemTime);
352
353          global.year = systemTime.wYear;
354          global.month = (Month)(systemTime.wMonth - 1);
355          global.day = systemTime.wDay;
356          global.hour = systemTime.wHour;
357          global.minute = systemTime.wMinute;
358          global.second = systemTime.wSecond;
359
360          return global;
361       #else
362          struct tm tm;
363          DateTime global;
364          time_t t = MakeTimeT(this);
365          // gmtime_r((time_t *)&this, &tm);
366          gmtime_r(&t, &tm);
367          global.year = tm.tm_year + 1900;
368          global.month = (Month)tm.tm_mon;
369          global.day = tm.tm_mday;
370          global.hour = tm.tm_hour;
371          global.minute = tm.tm_min;
372          global.second = tm.tm_sec;
373          global.dayInTheYear = tm.tm_yday;
374          global.dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
375          return global;
376       #endif
377       }
378    };
379    property SecSince1970 local
380    {
381       // TOFIX: warning: 'return' with a value, in function returning void
382       set { return value.global; }
383       get
384       {
385 #if defined(__WIN32__)
386          SYSTEMTIME systemTime, localTime;
387          DateTime utc, local;
388
389          utc = this;
390
391          systemTime.wYear = (short)utc.year;
392          systemTime.wMonth = (short)utc.month + 1;
393          systemTime.wDay = (short)utc.day;
394          systemTime.wHour = (short)utc.hour;
395          systemTime.wMinute = (short)utc.minute;
396          systemTime.wSecond = (short)utc.second;
397          systemTime.wMilliseconds = 0;
398
399          SystemTimeToTzSpecificLocalTime(null, &systemTime, &localTime);
400
401          local.year = localTime.wYear;
402          local.month = (Month)(localTime.wMonth - 1);
403          local.day = localTime.wDay;
404          local.hour = localTime.wHour;
405          local.minute = localTime.wMinute;
406          local.second = localTime.wSecond;
407          local.dayOfTheWeek = (DayOfTheWeek)localTime.wDayOfWeek;
408
409          local.FixDayOfYear();
410          return local;
411 #else
412          DateTime local;
413          struct tm tm;
414          time_t t = MakeTimeT(this);
415          //localtime_r((time_t *)&this, &tm);
416          localtime_r(&t, &tm);
417          local.year = tm.tm_year + 1900;
418          local.month = (Month)tm.tm_mon;
419          local.day = tm.tm_mday;
420          local.hour = tm.tm_hour;
421          local.minute = tm.tm_min;
422          local.second = tm.tm_sec;
423          local.dayInTheYear = tm.tm_yday;
424          local.dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
425          return local;
426 #endif
427       }
428    };
429 };
430
431 public class TimeStamp32 : uint32
432 {
433 public:
434    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
435    {
436       if(this || !this)
437       {
438          DateTime t = (SecSince1970)(int)this;
439          return t.OnGetString(tempString, fieldData, needClass);
440          // TOFIX:
441          // return ((DateTime)this).OnGetString(tempString, fieldData, needClass);
442       }
443       return tempString;
444    }
445
446    // Is this required?
447    int OnCompare(TimeStamp32 data2)
448    {
449       int result = 0;
450       if(this && data2)
451       {
452          if(this > data2)
453             result = 1;
454          else if(this < data2)
455             result = -1;
456       }
457       return result;
458    }
459 };
460
461 public class TimeStamp : SecSince1970
462 {
463    public property SecSince1970 {};
464 };
465 public enum DayOfTheWeek { sunday, monday, tuesday, wednesday, thursday, friday, saturday };
466 public struct DateTime
467 {
468    int year;
469    Month month;
470    int day, hour, minute, second;
471    DayOfTheWeek dayOfTheWeek;
472    int dayInTheYear;
473
474    bool GetLocalTime()
475    {
476    #if defined(__WIN32__)
477       SYSTEMTIME systemTime;
478       ::GetLocalTime(&systemTime);
479
480       year = systemTime.wYear;
481       month = (Month)(systemTime.wMonth - 1);
482       day = systemTime.wDay;
483       hour = systemTime.wHour;
484       minute = systemTime.wMinute;
485       second = systemTime.wSecond;
486
487       FixDayOfYear();
488       {
489          Date date { year, month, day };
490          dayOfTheWeek = date.dayOfTheWeek;
491       }
492    #else
493       struct tm tm;
494       time_t currentTime = time(null);
495       localtime_r(&currentTime, &tm);
496
497       year = tm.tm_year + 1900;
498       month = (Month)tm.tm_mon;
499       day = tm.tm_mday;
500       hour = tm.tm_hour;
501       minute = tm.tm_min;
502       second = tm.tm_sec;
503       dayInTheYear = tm.tm_yday;
504       dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
505    #endif
506
507       return true;
508    }
509
510    bool FixDayOfYear()
511    {
512       dayInTheYear = daysInAYearBeforeMonth[ISLEAP(year)][month] + day - 1;
513       return true;
514    }
515
516    property DateTime global
517    {
518       set { this = value.local; }
519       get
520       {
521       #if defined(__WIN32__)
522          SYSTEMTIME localTime, systemTime;
523          FILETIME fileTime, localFileTime;
524
525          localTime.wYear = (short)year;
526          localTime.wMonth = (short)month + 1;
527          localTime.wDay = (short)day;
528          localTime.wHour = (short)hour;
529          localTime.wMinute = (short)minute;
530          localTime.wSecond = (short)second;
531          localTime.wMilliseconds = 0;
532
533          SystemTimeToFileTime(&localTime, &fileTime);
534          LocalFileTimeToFileTime(&fileTime, &localFileTime);
535          FileTimeToSystemTime(&localFileTime, &systemTime);
536
537          value.year = systemTime.wYear;
538          value.month = (Month)(systemTime.wMonth - 1);
539          value.day = systemTime.wDay;
540          value.hour = systemTime.wHour;
541          value.minute = systemTime.wMinute;
542          value.second = systemTime.wSecond;
543       #else
544          struct tm tm;
545          //time_t t = (time_t)(SecSince1970)this;
546          time_t t = MakeTimeTfromDT(this);         
547          gmtime_r(&t, &tm);
548          value.year = tm.tm_year + 1900;
549          value.month = (Month)tm.tm_mon;
550          value.day = tm.tm_mday;
551          value.hour = tm.tm_hour;
552          value.minute = tm.tm_min;
553          value.second = tm.tm_sec;
554          value.dayInTheYear = tm.tm_yday;
555          value.dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
556       #endif
557       }
558    };
559    property DateTime local
560    {
561       set { this = value.global; }
562       get
563       {
564       #if defined(__WIN32__)
565          SYSTEMTIME systemTime, localTime;
566
567          systemTime.wYear = (short)year;
568          systemTime.wMonth = (short)month + 1;
569          systemTime.wDay = (short)day;
570          systemTime.wHour = (short)hour;
571          systemTime.wMinute = (short)minute;
572          systemTime.wSecond = (short)second;
573          systemTime.wMilliseconds = 0;
574
575          SystemTimeToTzSpecificLocalTime(null, &systemTime, &localTime);
576
577          value.year = localTime.wYear;
578          value.month = (Month)(localTime.wMonth - 1);
579          value.day = localTime.wDay;
580          value.hour = localTime.wHour;
581          value.minute = localTime.wMinute;
582          value.second = localTime.wSecond;
583          value.dayOfTheWeek = (DayOfTheWeek)localTime.wDayOfWeek;
584
585          value.FixDayOfYear();
586       #else
587          struct tm tm;
588          // time_t t = (time_t)(SecSince1970)this;
589          time_t t = MakeTimeTfromDT(this);
590          localtime_r(&t, &tm);
591          value.year = tm.tm_year + 1900;
592          value.month = (Month)tm.tm_mon;
593          value.day = tm.tm_mday;
594          value.hour = tm.tm_hour;
595          value.minute = tm.tm_min;
596          value.second = tm.tm_sec;
597          value.dayInTheYear = tm.tm_yday;
598          value.dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
599       #endif
600       }
601    };
602    property SecSince1970
603    {
604       set
605       {
606          int64 days, y;
607          int rem;
608             
609          days = value / SECS_PER_DAY;
610          rem = (int)(value % SECS_PER_DAY);
611
612          while(rem < 0)             { rem += SECS_PER_DAY; days--; }
613          while(rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; days++; }
614
615          hour = rem / SECS_PER_HOUR;
616
617          rem %= SECS_PER_HOUR;
618          minute = rem / 60;
619          second = rem % 60;
620
621          dayOfTheWeek = (EPOCH_WEEKDAY + days) % 7;
622          if(dayOfTheWeek < 0)
623             dayOfTheWeek += 7;
624
625          y = EPOCH_YEAR;
626          while(days < 0 || days >= daysInAYearBeforeMonth[ISLEAP(y)][12])
627          {
628             int64 yg = y + days / 365 - (days % 365 < 0);
629             days -= ((yg - y) * 365 + LEAPS_THRU_END_OF(yg - 1) - LEAPS_THRU_END_OF(y - 1));
630             y = yg;
631          }
632          year = (int)y;
633          {
634             const int * daysBeforeMonth = daysInAYearBeforeMonth[ISLEAP(y)];
635             dayInTheYear = (int)days;
636             for(y = 11; days < daysBeforeMonth[y]; y--);
637             days -= daysBeforeMonth[y];
638             month = (Month)y;
639             day = (int)(days + 1);
640          }
641       }
642
643       get
644       {
645          int month = this.month;
646          int monthRemainder = month % 12;
647          bool negativeMonthRemainder = monthRemainder < 0;
648          int monthYears = month / 12 - negativeMonthRemainder;
649          int year = this.year + monthYears;
650          // if(year >= 1970)
651          {
652             int a4 = (year       / 4) - !(year       & 3);
653             int b4 = (EPOCH_YEAR / 4) - !(EPOCH_YEAR & 3);
654             int a100 = a4 / 25 - (a4 % 25 < 0);
655             int b100 = b4 / 25 - (b4 % 25 < 0);
656             int a400 = a100 / 4;
657             int b400 = b100 / 4;
658             int leapDays = (a4 - b4) - (a100 - b100) + (a400 - b400);
659             int64 days = 365 * (year - EPOCH_YEAR) + leapDays;
660             month = monthRemainder + 12 * negativeMonthRemainder;
661             days += daysInAYearBeforeMonth[ISLEAP(year)][month] + day - 1;
662             return 60 * (60 * (24 * days + hour) + minute) + second;
663          }
664          return 0;
665       }
666    };
667
668    char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
669    {
670       static const char ampm[2][3] = { "AM", "PM" };
671       int hour = this.hour;
672       bool pm = false;
673       if(hour > 12) { hour -= 12; pm = true; }
674       else if(hour == 12) pm = true;
675       if(!hour) hour = 12;
676
677       if(!year && !day && !month && !this.hour && !minute && !second)
678          stringOutput[0] = 0;
679       else
680          sprintf(stringOutput, "%s %s %2d %2d:%02d:%02d %s %04d", 
681             daysNames[dayOfTheWeek], monthsNames[month], day, hour, minute, second, ampm[pm], year);
682
683       return stringOutput;
684    }
685
686    bool OnGetDataFromString(char * string)
687    {
688       char * s = CopyString(string);
689       char * tokens[20];
690       int count = TokenizeWith(s, 20, tokens, " ", false);
691       int c;
692       bool foundDayOfTheWeek = false;
693       bool foundDate = false;
694       DayOfTheWeek dayOfTheWeek;
695       int day = 0;
696       int minute = 0;
697       int second = 0;
698       int hour = 0;
699       int year = 0;
700
701       for(c = 0; c < count; c++)
702       {
703          int i;
704          for(i = 0; i<7; i++) 
705             if(!strcmpi(tokens[c], daysNames[i]) || !strcmpi(tokens[c], longDaysNames[i]))
706                break;               
707          if(i < 7) { dayOfTheWeek = (DayOfTheWeek)i; foundDayOfTheWeek = true; continue; }
708
709          for(i = 0; i<12; i++) 
710             if(!strcmpi(tokens[c], monthsNames[i]) || !strcmpi(tokens[c], longMonthsNames[i]))
711                break;               
712          if(i < 12) { month = (Month)i; continue; }
713
714          if(strchr(tokens[c], ':'))
715          {
716             char * subTokens[20];
717             int sCount = TokenizeWith(tokens[c], 20, subTokens, " :", false);
718             int t;
719             bool pm = false, am = false;
720             for(t = 0; t<sCount; t++)
721             {
722                if(!strcmpi(subTokens[t], "am")) am = true;
723                else if(!strcmpi(subTokens[t], "pm")) pm = true;
724                else if(t-am-pm == 0) hour = atoi(subTokens[t]);
725                else if(t-am-pm == 1) minute = atoi(subTokens[t]);
726                else if(t-am-pm == 2) second = atoi(subTokens[t]);               
727             }
728             
729             if(c < count - 1)
730             {
731                if(!strcmpi(tokens[c+1], "am")) am = true;
732                else if(!strcmpi(tokens[c+1], "pm")) pm = true;
733             }
734
735             if(am && hour == 12) hour = 0;
736             else if(pm && hour < 12) hour += 12;
737
738             continue;
739          }
740          
741          if(!foundDate)
742          {
743             if(strchr(tokens[c], '/') || strchr(tokens[c], '-'))
744             {
745                Date date;
746                if(date.OnGetDataFromString(tokens[c]))
747                {
748                   day = date.day;
749                   year = date.year;
750                   month = date.month;
751                }
752                foundDate = true;
753             }
754             else
755             {
756                i = atoi(tokens[c]);
757                if(i > 31)
758                {
759                   year = i;
760                   continue;
761                }
762                else if(i)
763                   day = i;
764             }
765          }
766       }
767       if(day)
768       {
769          Date date { year, month, day };
770          this.dayOfTheWeek = date.dayOfTheWeek;
771          this.day = day;
772          this.minute = minute;
773          this.second = second;
774          this.hour = hour;
775          this.year = year;
776       }
777       else if(foundDayOfTheWeek)
778       {
779          SecSince1970 weWant;
780          GetLocalTime();
781          if(dayOfTheWeek <= this.dayOfTheWeek) dayOfTheWeek += 7;
782          weWant = (SecSince1970)this + (int)(dayOfTheWeek - this.dayOfTheWeek) * 24 * 60 * 60;
783          this = (DateTime)weWant;
784       }
785       else if(!strcmpi(s, "today") || !strcmpi(s, "now"))
786          GetLocalTime();
787       else if(!strcmpi(s, "tomorrow"))
788       {
789          SecSince1970 weWant;
790          GetLocalTime();
791          weWant = (SecSince1970)this + 24 * 60 * 60;
792          this = (DateTime)weWant;
793       }
794       else if(!strcmpi(s, "yesterday"))
795       {
796          SecSince1970 weWant;
797          GetLocalTime();
798          weWant = (SecSince1970)this - 24 * 60 * 60;
799          this = (DateTime)weWant;
800       }
801       else if(!s[0])
802       {
803          this = { };
804          delete s;
805          return true;
806       }
807       delete s;
808       return this.day != 0;
809    }
810 };
811
812 public Time GetTime(void)
813 {
814 #if defined(__WIN32__)
815    return timeGetTime() / 1000.0;
816 #elif defined(__unix__) || defined(__APPLE__)
817    struct timeval tp;
818    struct timezone tzp;
819    static int secbase = 0;
820
821    gettimeofday(&tp, &tzp);
822
823    if(!secbase)
824    {
825       secbase = tp.tv_sec;
826       return tp.tv_usec / 1000000.0;
827    }
828    return (tp.tv_sec - secbase) + tp.tv_usec / 1000000.0;
829 #endif
830 }
831
832 public void Sleep(Seconds seconds)
833 {
834 #if defined(__WIN32__)
835    ::Sleep((uint)(seconds * 1000));
836 #else
837    if(!seconds)
838       sched_yield();
839    else
840    {
841       // usleep((uint)(seconds * 1000000));
842       struct timeval tv = { (int)seconds, (int)((seconds - (int)seconds) * 1000000) };
843       select(0,null,null,null, &tv);
844    }
845 #endif
846 }
847
848 public void RandomSeed(uint seed)
849 {
850 #if defined(__linux__) || defined(__DJGPP__)
851    srandom(seed);
852 #else
853    srand(seed);
854 #endif
855 }
856
857 public int GetRandom(int lo, int hi)
858 {
859    if(hi >= lo)
860    {
861 #if defined(__linux__) || defined(__DJGPP__)
862       // return lo+(int)(((uint)(hi - lo) + 1.0)*random()/(RAND_MAX+1.0));
863       return (int)(lo + ((uint)(hi - lo) + 1.0) * random() / (RAND_MAX + 1.0));
864 #else
865       // return lo+(int)(((uint)(hi - lo) + 1.0)*rand()/(RAND_MAX+1.0));
866       return (int)(lo + ((uint)(hi - lo) + 1.0) * rand() / (RAND_MAX + 1.0));
867 #endif
868    }
869    else
870       return lo;
871 }