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