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