8 #define FileName _FileName
9 #define Instance _Instance
14 #define uint64 _uint64
15 #define Alignment _Alignment
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
23 #elif defined(__unix__) || defined(__APPLE__)
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;
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))))
52 const int daysInAYearBeforeMonth[2][13] =
55 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
57 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
60 int monthLengths[2][12] =
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 }
66 char daysNames[7][4] =
68 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
70 char monthsNames[12][4] =
72 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
75 #if defined(__WIN32__)
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 ;
80 static int TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
82 int limit_day, dayinsecs;
84 if(date->wMonth < compareDate->wMonth) return -1;
85 if(date->wMonth > compareDate->wMonth) return 1;
87 if(compareDate->wDayOfWeek <= 6)
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])
98 limit_day = compareDate->wDay;
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;
106 static uint TIME_CompTimeZoneID(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, bool islocal)
109 bool beforeStandardDate, afterDaylightDate;
110 DWORD retval = TIME_ZONE_ID_INVALID;
115 if (pTZinfo->DaylightDate.wMonth != 0)
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)
123 SetLastError(ERROR_INVALID_PARAMETER);
124 return TIME_ZONE_ID_INVALID;
129 FILETIME2LL( lpFileTime, llTime );
130 llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias ) * (LONGLONG)600000000;
131 LL2FILETIME( llTime, &ftTemp)
132 lpFileTime = &ftTemp;
135 FileTimeToSystemTime(lpFileTime, &SysTime);
137 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
139 return TIME_ZONE_ID_INVALID;
141 beforeStandardDate = ret < 0;
145 llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias ) * (LONGLONG)600000000;
146 LL2FILETIME( llTime, &ftTemp)
147 FileTimeToSystemTime(lpFileTime, &SysTime);
150 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
152 return TIME_ZONE_ID_INVALID;
154 afterDaylightDate = ret >= 0;
156 retval = TIME_ZONE_ID_STANDARD;
157 if( pTZinfo->DaylightDate.wMonth < pTZinfo->StandardDate.wMonth )
159 if( beforeStandardDate && afterDaylightDate )
160 retval = TIME_ZONE_ID_DAYLIGHT;
162 else if( beforeStandardDate || afterDaylightDate )
163 retval = TIME_ZONE_ID_DAYLIGHT;
166 retval = TIME_ZONE_ID_UNKNOWN;
170 static bool TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, bool islocal, LONG *pBias)
172 LONG bias = pTZinfo->Bias;
173 DWORD tzid = TIME_CompTimeZoneID( pTZinfo, lpFileTime, islocal);
175 if( tzid == TIME_ZONE_ID_INVALID)
177 if (tzid == TIME_ZONE_ID_DAYLIGHT)
178 bias += pTZinfo->DaylightBias;
179 else if (tzid == TIME_ZONE_ID_STANDARD)
180 bias += pTZinfo->StandardBias;
185 static bool _TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime)
190 TIME_ZONE_INFORMATION tzinfo;
192 if(lpTimeZoneInformation)
194 memcpy(&tzinfo, lpTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
198 if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
202 if (!SystemTimeToFileTime(lpLocalTime, &ft))
205 if (!TIME_GetTimezoneBias(&tzinfo, &ft, true, &lBias))
208 t += (LONGLONG)lBias * 600000000;
210 return (bool)FileTimeToSystemTime(&ft, lpUniversalTime);
216 public class Time : double
218 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
224 value = (int)(time / (60 * 60 * 24));
228 sprintf(temp, "%d:", value);
229 strcat(tempString, temp);
230 time -= value * 60 * 60 * 24;
232 value = (int)(time / (60 * 60));
235 sprintf(temp, "%d:", value);
236 strcat(tempString, temp);
237 time -= value * 60 * 60;
240 value = (int)(time / 60);
241 sprintf(temp, "%d:", value);
242 strcat(tempString, temp);
246 sprintf(temp, "%02d", value);
247 strcat(tempString, temp);
252 sprintf(temp, "%f" time);
253 strcat(tempString, temp+1);
259 public class Seconds : Time { public property Time {} };
261 #if !defined(__WIN32__)
262 static time_t MakeTimeT(SecSince1970 t)
267 tm.tm_year = dt.year - 1900;
268 tm.tm_mon = dt.month;
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);
279 static time_t MakeTimeTfromDT(DateTime dt)
283 tm.tm_year = dt.year - 1900;
284 tm.tm_mon = dt.month;
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);
297 public class SecSince1970 : int64
299 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
303 // TOFIX: passing argument 2 of '__ecereProp___ecereNameSpace__ecere__sys__DateTime_Set___ecereNameSpace__ecere__sys__SecSince1970' makes integer from pointer without a cast
305 return t.OnGetString(tempString, fieldData, needClass);
307 // return ((DateTime)this).OnGetString(tempString, fieldData, needClass);
313 int OnCompare(SecSince1970 data2)
320 else if(this < data2)
326 property SecSince1970 global
328 // TOFIX: 'return' with a value, in function returning void
329 set { return value.local; }
332 #if defined(__WIN32__)
333 SYSTEMTIME localTime, systemTime;
334 FILETIME fileTime, localFileTime;
335 DateTime input, global;
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;
348 SystemTimeToFileTime(&localTime, &fileTime);
349 LocalFileTimeToFileTime(&fileTime, &localFileTime);
350 FileTimeToSystemTime(&localFileTime, &systemTime);
353 _TzSpecificLocalTimeToSystemTime(null, &localTime, &systemTime);
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;
366 time_t t = MakeTimeT(this);
367 // gmtime_r((time_t *)&this, &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;
381 property SecSince1970 local
383 // TOFIX: warning: 'return' with a value, in function returning void
384 set { return value.global; }
387 #if defined(__WIN32__)
388 SYSTEMTIME systemTime, localTime;
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;
401 SystemTimeToTzSpecificLocalTime(null, &systemTime, &localTime);
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;
411 local.FixDayOfYear();
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;
433 public class TimeStamp32 : uint32
436 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
440 DateTime t = (SecSince1970)(int)this;
441 return t.OnGetString(tempString, fieldData, needClass);
443 // return ((DateTime)this).OnGetString(tempString, fieldData, needClass);
449 int OnCompare(TimeStamp32 data2)
456 else if(this < data2)
463 public class TimeStamp : SecSince1970
465 public property SecSince1970 {};
467 public enum DayOfTheWeek { sunday, monday, tuesday, wednesday, thursday, friday, saturday };
468 public struct DateTime
472 int day, hour, minute, second;
473 DayOfTheWeek dayOfTheWeek;
478 #if defined(__WIN32__)
479 SYSTEMTIME systemTime;
480 ::GetLocalTime(&systemTime);
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;
491 Date date { year, month, day };
492 dayOfTheWeek = date.dayOfTheWeek;
496 time_t currentTime = time(null);
497 localtime_r(¤tTime, &tm);
499 year = tm.tm_year + 1900;
500 month = (Month)tm.tm_mon;
505 dayInTheYear = tm.tm_yday;
506 dayOfTheWeek = (DayOfTheWeek)tm.tm_wday;
514 dayInTheYear = daysInAYearBeforeMonth[ISLEAP(year)][month] + day - 1;
518 property DateTime global
520 set { this = value.local; }
523 #if defined(__WIN32__)
524 SYSTEMTIME localTime, systemTime;
525 FILETIME fileTime, localFileTime;
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;
535 SystemTimeToFileTime(&localTime, &fileTime);
536 LocalFileTimeToFileTime(&fileTime, &localFileTime);
537 FileTimeToSystemTime(&localFileTime, &systemTime);
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;
547 //time_t t = (time_t)(SecSince1970)this;
548 time_t t = MakeTimeTfromDT(this);
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;
561 property DateTime local
563 set { this = value.global; }
566 #if defined(__WIN32__)
567 SYSTEMTIME systemTime, localTime;
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;
577 SystemTimeToTzSpecificLocalTime(null, &systemTime, &localTime);
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;
587 value.FixDayOfYear();
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;
604 property SecSince1970
611 days = value / SECS_PER_DAY;
612 rem = (int)(value % SECS_PER_DAY);
614 while(rem < 0) { rem += SECS_PER_DAY; days--; }
615 while(rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; days++; }
617 hour = rem / SECS_PER_HOUR;
619 rem %= SECS_PER_HOUR;
623 dayOfTheWeek = (EPOCH_WEEKDAY + days) % 7;
628 while(days < 0 || days >= daysInAYearBeforeMonth[ISLEAP(y)][12])
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));
636 const int * daysBeforeMonth = daysInAYearBeforeMonth[ISLEAP(y)];
637 dayInTheYear = (int)days;
638 for(y = 11; days < daysBeforeMonth[y]; y--);
639 days -= daysBeforeMonth[y];
641 day = (int)(days + 1);
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;
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);
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;
670 char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
672 static const char ampm[2][3] = { "AM", "PM" };
673 int hour = this.hour;
675 if(hour > 12) { hour -= 12; pm = true; }
676 else if(hour == 12) pm = true;
679 if(!year && !day && !month && !this.hour && !minute && !second)
682 sprintf(stringOutput, "%s %s %2d %2d:%02d:%02d %s %04d",
683 daysNames[dayOfTheWeek], monthsNames[month], day, hour, minute, second, ampm[pm], year);
688 bool OnGetDataFromString(char * string)
690 char * s = CopyString(string);
692 int count = TokenizeWith(s, 20, tokens, " ", false);
694 bool foundDayOfTheWeek = false;
695 bool foundDate = false;
696 DayOfTheWeek dayOfTheWeek;
703 for(c = 0; c < count; c++)
707 if(!strcmpi(tokens[c], daysNames[i]) || !strcmpi(tokens[c], longDaysNames[i]))
709 if(i < 7) { dayOfTheWeek = (DayOfTheWeek)i; foundDayOfTheWeek = true; continue; }
711 for(i = 0; i<12; i++)
712 if(!strcmpi(tokens[c], monthsNames[i]) || !strcmpi(tokens[c], longMonthsNames[i]))
714 if(i < 12) { month = (Month)i; continue; }
716 if(strchr(tokens[c], ':'))
718 char * subTokens[20];
719 int sCount = TokenizeWith(tokens[c], 20, subTokens, " :", false);
721 bool pm = false, am = false;
722 for(t = 0; t<sCount; t++)
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]);
733 if(!strcmpi(tokens[c+1], "am")) am = true;
734 else if(!strcmpi(tokens[c+1], "pm")) pm = true;
737 if(am && hour == 12) hour = 0;
738 else if(pm && hour < 12) hour += 12;
745 if(strchr(tokens[c], '/') || strchr(tokens[c], '-'))
748 if(date.OnGetDataFromString(tokens[c]))
771 Date date { year, month, day };
772 this.dayOfTheWeek = date.dayOfTheWeek;
774 this.minute = minute;
775 this.second = second;
779 else if(foundDayOfTheWeek)
783 if(dayOfTheWeek <= this.dayOfTheWeek) dayOfTheWeek += 7;
784 weWant = (SecSince1970)this + (int)(dayOfTheWeek - this.dayOfTheWeek) * 24 * 60 * 60;
785 this = (DateTime)weWant;
787 else if(!strcmpi(s, "today") || !strcmpi(s, "now"))
789 else if(!strcmpi(s, "tomorrow"))
793 weWant = (SecSince1970)this + 24 * 60 * 60;
794 this = (DateTime)weWant;
796 else if(!strcmpi(s, "yesterday"))
800 weWant = (SecSince1970)this - 24 * 60 * 60;
801 this = (DateTime)weWant;
810 return this.day != 0;
814 public Time GetTime(void)
816 #if defined(__WIN32__)
817 return timeGetTime() / 1000.0;
818 #elif defined(__unix__) || defined(__APPLE__)
821 static int secbase = 0;
823 gettimeofday(&tp, &tzp);
828 return tp.tv_usec / 1000000.0;
830 return (tp.tv_sec - secbase) + tp.tv_usec / 1000000.0;
834 public void Sleep(Seconds seconds)
836 #if defined(__WIN32__)
837 ::Sleep((uint)(seconds * 1000));
843 // usleep((uint)(seconds * 1000000));
844 struct timeval tv = { (int)seconds, (int)((seconds - (int)seconds) * 1000000) };
845 select(0,null,null,null, &tv);
850 public void RandomSeed(uint seed)
852 #if defined(__linux__) || defined(__DJGPP__)
859 public int GetRandom(int lo, int hi)
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));
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));