//+------------------------------------------------------------------+ //| GenerateCases.mq5 | //| CalendarDifference Test Generator | //+------------------------------------------------------------------+ #property script_show_inputs #include "..\TimeUtils.mqh" input int RandomPairs = 100000; const datetime MIN_TIME = D'1970.01.01 00:00:00'; const datetime MAX_TIME = D'3000.12.31 23:59:59'; //--------------------------------------------------------------- // SplitMix64 //--------------------------------------------------------------- struct SplitMix64 { ulong state; SplitMix64() { state = (ulong)GetTickCount64(); } ulong Next() { ulong z = (state += 0x9E3779B97F4A7C15); z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9; z = (z ^ (z >> 27)) * 0x94D049BB133111EB; return z ^ (z >> 31); } }; SplitMix64 RNG; //--------------------------------------------------------------- string ISO(datetime t) { MqlDateTime s; TimeToStructFast(t, s); return StringFormat("%04d-%02d-%02dT%02d:%02d:%02d", s.year, s.mon, s.day, s.hour, s.min, s.sec); } //--------------------------------------------------------------- void WritePair(int file, datetime from, datetime to) { MqlDateTime diff; CalendarDifference(from, to, diff); FileWrite(file, ISO(from), ISO(to), diff.year, diff.mon, diff.day, diff.hour, diff.min, diff.sec); } //+------------------------------------------------------------------+ //| Writes the pair only if both timestamps are in range | //+------------------------------------------------------------------+ void WritePairIfValid(const int file, const datetime from, const datetime to) { if(to < MIN_TIME || to > MAX_TIME) return; WritePair(file, from, to); } //--------------------------------------------------------------- datetime RandomTime() { ulong span = (ulong)(MAX_TIME - MIN_TIME); return (datetime)(MIN_TIME + (datetime)(RNG.Next() % span)); } //--------------------------------------------------------------- void GenerateMonthEnds(int file) { for(int year=1970; year<=3000; year++) { for(int month=1; month<=12; month++) { int last=DaysInMonth(year,month); for(int day=MathMax(1,last-3); day<=last; day++) { datetime t=DateFrom(year,month,day); WritePairIfValid(file, t, AddDays(t, -2)); WritePairIfValid(file, t, AddDays(t, -1)); WritePairIfValid(file, t, AddDays(t, 1)); WritePairIfValid(file, t, AddDays(t, 2)); WritePairIfValid(file, t, AddMonths(t, -1)); WritePairIfValid(file, t, AddMonths(t, 1)); WritePairIfValid(file, t, AddYears(t, -1)); WritePairIfValid(file, t, AddYears(t, 1)); } } } } //--------------------------------------------------------------- void GenerateLeapYears(int file) { for(int year=1970; year<=3000; year++) { if(!IsLeapYear(year)) continue; datetime feb28=DateFrom(year,2,28); WritePairIfValid(file,feb28,AddDays(feb28,1)); WritePairIfValid(file,feb28,AddDays(feb28,2)); datetime feb29=DateFrom(year,2,29); WritePairIfValid(file,feb29,AddYears(feb29,1)); WritePairIfValid(file,feb29,AddYears(feb29,4)); WritePairIfValid(file,feb29,AddMonths(feb29,12)); } } //--------------------------------------------------------------- void GenerateYearBoundaries(int file) { for(int year=1970; year<=3000; year++) { datetime end=DateFrom(year,12,31,23,59,59); WritePairIfValid(file,end,AddSeconds(end,1)); WritePairIfValid(file,end,AddDays(end,1)); WritePairIfValid(file,end,AddMonths(end,1)); WritePairIfValid(file,end,AddYears(end,1)); } } //--------------------------------------------------------------- void GenerateQuarterBoundaries(int file) { const int months[]={3,6,9,12}; for(int year=1970; year<=3000; year++) { for(int i=0;i<4;i++) { int month=months[i]; datetime t=DateFrom( year, month, DaysInMonth(year,month)); WritePairIfValid(file,t,AddDays(t,1)); WritePairIfValid(file,t,AddMonths(t,3)); } } } //--------------------------------------------------------------- void GenerateRandom(int file) { for(int i=0;i