TimeUtils/TimeUtils.mqh
amrali d9b952c4ee
2026-07-20 07:45:57 +03:00

2466 lines
107 KiB
MQL5

//+------------------------------------------------------------------+
//| TimeUtils.mqh |
//| Copyright © 2026, Amr Ali |
//| https://www.mql5.com/en/users/amrali |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2026, Amr Ali"
#property link "https://www.mql5.com/en/users/amrali"
#property version "2.55"
#property description "High-performance functions for dealing with time."
// Updates:
// 2024.12.03 - v1.10 : Initial release.
// 2024.12.05 - v1.15 : Added functions for business days and for Nth() weekday of the month. Optimized calculations in DaysInMonth() function.
// 2024.12.09 - v1.20 : Added TimeFormat() function to format the time according to the passed string of tokens.
// 2024.12.09 - v1.25 : Optimized calculations in TimeToStructFast() function.
// 2024.12.10 - v1.30 : Optimized TimeFormat(), StartOfYear() and EndOfYear() functions. Updated descriptions of some functions.
// 2024.12.15 - v1.35 : Optimized NthWeekdayOfYearMonth() function.
// 2024.12.18 - v1.40 : Added IsCurrentXXX(), IsToday(), IsTomorrow() and IsYesterday() functions.
// 2024.12.19 - v1.45 : Optimized AddMonths() and NthWeekdayOfYearMonth() functions.
// 2024.12.20 - v1.50 : More code clean-up.
// 2024.12.21 - v1.55 : Simplified calculations in AddMonths(): replaced the complex logic of adjusting months and years with a simpler total months calculation.
// 2026.06.22 - v1.60 : Optimized AddBusinessDays() and DifferenceInBusinessDays() functions. Added various IsXXX() check functions.
// 2026.07.06 - v2.00 : New March-based conversion routines derived from the Neri–Schneider calendar algorithm + validation script. Removed "performance" mode.
// 2026.07.07 - v2.10 : Added DaysInYear(), LastDayOf(), MinuteOf(), HourOf() and CalendarDifferenceToString() functions.
// 2026.07.10 - v2.30 : Added date construction, quarter, calendar difference, and relative-date helper functions. Introduced configurable week start and renamed several functions for a cleaner, more consistent API.
// 2026.07.12 - v2.35 : Updated CalendarDifferenceToString() to return the precise elapsed time, including hours, minutes, and seconds.
// 2026.07.14 - v2.40 : Redesigned the year/month decomposition in CalendarDifferenceToString() to correctly handle February 29 edge cases. Simplified and optimized the DifferenceInXXX() functions. Added epoch-based index functions.
// 2026.07.15 - v2.45 : Added CalendarDifference() to return the calendar difference between two dates, broken down into years, months, days, hours, minutes, and seconds.
// 2026.07.18 - v2.50 : Added AddPeriod() and SubPeriod() for calendar period arithmetic. Added WithXxx() functions for replacing individual date/time fields. Added IsInSession() for checking recurring daily sessions.
// 2026.07.20 - v2.55 : Optimized week-based functions. Added SessionOverlap() for calculating overlapping time intervals. Improved documentation and API comments.
#ifdef __MQL4__
#property strict
#endif
#ifndef TIMEUTILS_UNIQUE_HEADER_ID_H
#define TIMEUTILS_UNIQUE_HEADER_ID_H
// First day of the week used by all week-related functions.
// Optionally, override the default before including this header:
//
// #define TIMEUTILS_FIRST_DAY_OF_WEEK SUNDAY
// #include "TimeUtils.mqh"
//
// Valid values: SUNDAY or MONDAY (default: MONDAY).
#ifndef TIMEUTILS_FIRST_DAY_OF_WEEK
#define TIMEUTILS_FIRST_DAY_OF_WEEK MONDAY
#endif
//####################################################################
//# #
//# Construction & Conversion #
//# #
//####################################################################
//DateFrom(2026, 7, 20)
//DateFromString("2026.07.20 14:30")
//TimeToStructFast(datetime, MqlDateTime)
//StructToTimeFast(MqlDateTime)
//####################################################################
//# #
//# Calendar Fields & Components #
//# #
//####################################################################
//+==================================================================+
//| Calendar Fields |
//+==================================================================+
// Year(datetime) Month(datetime)
// Day(datetime) Hour(datetime)
// Minute(datetime) Second(datetime)
// DayOfWeek(datetime) datetime DateOnly(tm)
// DayOfYear(datetime) datetime TimeOnly(tm)
//####################################################################
//# #
//# Calendar Indices & Positions #
//# #
//####################################################################
//+==================================================================+
//| Absolute Indices |
//+==================================================================+
// YearIndex(datetime) MonthIndex(datetime)
// QuarterIndex(datetime) WeekIndex(datetime)
// DayIndex(datetime) HourIndex(datetime)
// MinuteIndex(datetime)
//+==================================================================+
//| Position Within Calendar |
//+==================================================================+
// Quarter(datetime)
// WeekOfYear(datetime) WeekOfMonth(datetime)
// HourOfYear(datetime) MinuteOfYear(datetime)
// HourOfQuarter(datetime) MinuteOfQuarter(datetime)
// HourOfMonth(datetime) MinuteOfMonth(datetime)
// HourOfWeek(datetime) MinuteOfWeek(datetime)
// MinuteOfDay(datetime)
// SecsElapsedOfYear(datetime) SecsElapsedOfQuarter(datetime)
// SecsElapsedOfMonth(datetime) SecsElapsedOfWeek(datetime)
// SecsElapsedOfDay(datetime) SecsElapsedOfHour(datetime)
// SecsElapsedOfMinute(datetime) SecsElapsedOfEpoch(datetime)
// SecondsSinceMidnight(datetime)
//####################################################################
//# #
//# Navigation / Manipulation #
//# #
//####################################################################
//+==================================================================+
//| Period Boundaries |
//+==================================================================+
// datetime StartOfMinute(datetime) datetime EndOfMinute(datetime)
// datetime StartOfHour(datetime) datetime EndOfHour(datetime)
// datetime StartOfDay(datetime) datetime EndOfDay(datetime)
// datetime StartOfWeek(datetime) datetime EndOfWeek(datetime)
// datetime StartOfMonth(datetime) datetime EndOfMonth(datetime)
// datetime StartOfQuarter(datetime) datetime EndOfQuarter(datetime)
// datetime StartOfYear(datetime) datetime EndOfYear(datetime)
// datetime StartOfToday() datetime EndOfToday()
// datetime StartOfTomorrow() datetime EndOfTomorrow()
// datetime StartOfYesterday() datetime EndOfYesterday()
//+==================================================================+
//| Calendar Navigation |
//+==================================================================+
// datetime LastDayOfWeek(datetime) datetime FirstWeekdayOfMonth(datetime, MONDAY)
// datetime LastDayOfMonth(datetime) datetime LastWeekdayOfMonth(datetime, FRIDAY)
// datetime LastDayOfQuarter(datetime) datetime NthWeekdayOfYearMonth(2026, 11, Nth, FRIDAY)
// datetime LastDayOfYear(datetime)
// datetime NextDayOfWeek(datetime, MONDAY) datetime PreviousDayOfWeek(datetime, MONDAY)
// datetime NextSunday(datetime) datetime PreviousSunday(datetime)
// datetime NextMonday(datetime) datetime PreviousMonday(datetime)
// datetime NextTuesday(datetime) datetime PreviousTuesday(datetime)
// datetime NextWednesday(datetime) datetime PreviousWednesday(datetime)
// datetime NextThursday(datetime) datetime PreviousThursday(datetime)
// datetime NextFriday(datetime) datetime PreviousFriday(datetime)
// datetime NextSaturday(datetime) datetime PreviousSaturday(datetime)
//+==================================================================+
//| Rounding & Alignment |
//+==================================================================+
// datetime RoundToMinute(datetime) datetime CeilToMinute(datetime)
// datetime RoundToHour(datetime) datetime CeilToHour(datetime)
// datetime RoundToDay(datetime) datetime CeilToDay(datetime)
// datetime RoundToWeek(datetime) datetime CeilToWeek(datetime)
//+==================================================================+
//| Field Replacement |
//+==================================================================+
// datetime WithSecond(datetime, 30) datetime WithMonth(datetime, 12)
// datetime WithMinute(datetime, 45) datetime WithYear(datetime, 2030)
// datetime WithHour(datetime, 14) datetime WithTime(datetime, 14, 30, 0)
// datetime WithDay(datetime, 15) datetime WithDate(datetime, 2026, 7, 20)
// datetime WithDayOfWeek(datetime, FRIDAY)
//+==================================================================+
//| Arithmetic |
//+==================================================================+
// datetime AddSeconds(datetime, 30) datetime SubSeconds(datetime, 30)
// datetime AddMinutes(datetime, 15) datetime SubMinutes(datetime, 15)
// datetime AddHours(datetime, 8) datetime SubHours(datetime, 8)
// datetime AddDays(datetime, 5) datetime SubDays(datetime, 5)
// datetime AddBusinessDays(datetime, 5) datetime SubBusinessDays(datetime, 5)
// datetime AddWeeks(datetime, 2) datetime SubWeeks(datetime, 2)
// datetime AddMonths(datetime, 3) datetime SubMonths(datetime, 3)
// datetime AddQuarters(datetime, 2) datetime SubQuarters(datetime, 2)
// datetime AddYears(datetime, 10) datetime SubYears(datetime, 10)
// datetime AddPeriod(datetime, MqlDateTime period)
// datetime SubPeriod(datetime, MqlDateTime period)
//####################################################################
//# #
//# Differences & Duration #
//# #
//####################################################################
//+==================================================================+
//| Exact Time Durations |
//+==================================================================+
// DifferenceInSeconds(from, to) DifferenceInBusinessDays(from, to)
// DifferenceInMinutes(from, to) DifferenceInWeekendDays(from, to)
// DifferenceInHours(from, to)
// DifferenceInDays(from, to)
// DifferenceInWeeks(from, to)
// DifferenceInMonths(from, to)
// DifferenceInQuarters(from, to)
// DifferenceInYears(from, to)
//+==================================================================+
//| Calendar Differences |
//+==================================================================+
// DifferenceInCalendarDays(from, to) DifferenceInCalendarWeeks(from, to)
// DifferenceInCalendarMonths(from, to) DifferenceInCalendarQuarters(from, to)
// DifferenceInCalendarYears(from, to)
// CalendarDifference(from, to, MqlDateTime period)
// CalendarDifferenceToString(from, to)
//####################################################################
//# #
//# Validation & Comparison #
//# #
//####################################################################
//+==================================================================+
//| Day Checks |
//+==================================================================+
// IsWeekday(datetime) IsWeekend(datetime)
// IsSunday(datetime) IsThursday(datetime)
// IsMonday(datetime) IsFriday(datetime)
// IsTuesday(datetime) IsSaturday(datetime)
// IsWednesday(datetime)
// IsFirstDayOfMonth(datetime) IsToday(datetime)
// IsLastDayOfMonth(datetime) IsTomorrow(datetime)
// IsYesterday(datetime)
//+==================================================================+
//| Current Period |
//+==================================================================+
// IsCurrentMinute(datetime) IsCurrentMonth(datetime)
// IsCurrentHour(datetime) IsCurrentQuarter(datetime)
// IsCurrentWeek(datetime) IsCurrentYear(datetime)
//+==================================================================+
//| Equality |
//+==================================================================+
// IsSameMinute(a, b) IsSameMonth(a, b)
// IsSameHour(a, b) IsSameQuarter(a, b)
// IsSameDay(a, b) IsSameYear(a, b)
// IsSameWeek(a, b)
//+==================================================================+
//| Daily Trading Sessions |
//+==================================================================+
// IsInSession(datetime, IsInSession("08:00", "17:00")
// 8, 0, 17, 0)
// IsInSession(8, 0, 17, 0) bool SessionOverlap()
//####################################################################
//# #
//# Calendar Information #
//# #
//####################################################################
// DaysInMonth(2026, 7) WeeksInMonth(2026, 7)
// DaysInYear(2026) WeeksInYear(2026)
// IsLeapYear(2028)
//####################################################################
//# #
//# Formatting & Utilities #
//# #
//####################################################################
// DayName(ENUM_DAY_OF_WEEK)
// MonthName(7)
// SecondsToString(3661)
// t2s(datetime, TIME_DATE | TIME_MINUTES)
// TimeFormat(datetime, "YYYY.MM.DD hh:mm")
//+------------------------------------------------------------------+
//| Time unit conversion constants |
//+------------------------------------------------------------------+
#define MINSECS 60ULL
#define HOURSECS 3600ULL
#define DAYSECS 86400ULL
#define WEEKSECS 604800ULL
#define DAYS_PER_4_YEARS 1461U // (4 * 365) + 1
#define DAYS_PER_400_YEARS 146097U // DAYS_PER_4_YEARS * 100 - 3 non-leap century years.
#define DAYS_TO_1970 719162 // Number of days from 1/1/0001 to 12/31/1969.
#define MARCH1_BASED_DOY 306 // Number of days between March 1 and January 1.
// Offset used to align calendar week boundaries.
// 1970-01-01 (Unix epoch) was a Thursday.
#define WEEK_OFFSET \
((THURSDAY - (int)TIMEUTILS_FIRST_DAY_OF_WEEK) * DAYSECS)
//####################################################################
//# #
//# Construction #
//# #
//####################################################################
//+==================================================================+
//| Create datetime From Components |
//+==================================================================+
//+------------------------------------------------------------------+
//| Create a datetime value from the specified date and time. |
//+------------------------------------------------------------------+
datetime DateFrom(const int year, // Year
const int mon, // Month
const int day, // Day
const int hour = 0, // Hour
const int min = 0, // Minutes
const int sec = 0) // Seconds
{
MqlDateTime dt = {year, mon, day, hour, min, sec};
return StructToTimeFast(dt);
}
//+------------------------------------------------------------------+
//| Create a datetime from a formatted date/time string. |
//+------------------------------------------------------------------+
datetime DateFromString(const string text)
{
return StringToTime(text);
}
//+------------------------------------------------------------------+
//| Faster alternative to MQL's StructToTime() function. |
//| Converts a structure variable MqlDateTime into a value of |
//| datetime type and returns the resulting value containing |
//| the number of seconds since 01.01.1970. |
//+------------------------------------------------------------------+
datetime StructToTimeFast(const MqlDateTime& dt_struct)
{
const uint j = dt_struct.mon < 3;
const uint y = dt_struct.year - j;
const uint m = j ? dt_struct.mon + 12 : dt_struct.mon;
const uint f = (979 * m - 2918) / 32; // days before month
const uint n = dt_struct.day - 1 + f + 365*y + (y/4) - (y/100) + (y/400) - DAYS_TO_1970 - MARCH1_BASED_DOY;
return (datetime)((n * DAYSECS) + (dt_struct.hour * HOURSECS) + (dt_struct.min * MINSECS) + dt_struct.sec);
}
//####################################################################
//# #
//# Calendar Components #
//# #
//####################################################################
//+==================================================================+
//| Break datetime To Components |
//+==================================================================+
//+------------------------------------------------------------------+
//| Faster alternative to MQL's TimeToStruct() function. |
//| Converts a value of datetime type (number of seconds |
//| since 01.01.1970) into a structure variable MqlDateTime. |
//| https://github.com/cassioneri/eaf/blob/main/algorithms/neri_schneider.hpp
//+------------------------------------------------------------------+
bool TimeToStructFast(const datetime time, MqlDateTime& dt_struct)
{
uint n = (uint)(time / DAYSECS) ; // Unix day
uint N = n + 12699422 ; // Computational calendar day
uint a = 4 * N + 3 ; // N_1
uint c = a / DAYS_PER_400_YEARS ; // century
uint e = a % DAYS_PER_400_YEARS / 4 ; // [0, 36524] - dayOfCentury
uint b = 4 * e + 3 ; // N_2
uint z = b / DAYS_PER_4_YEARS ; // [0, 99] - yearOfCentury
uint h = b % DAYS_PER_4_YEARS / 4 ; // [0, 365] - Days since 1 March
uint d = 2141 * h + 197913 ; // N_3
uint M = d / 65536 ; // [3, 14] - Month
uint D = d % 65536 / 2141U ; // [0, 30] - Day
uint Y = 100 * c + z ; // Year
uint J = h >= MARCH1_BASED_DOY ; // JanFeb
uint l = z ? (z % 4 == 0) : (c % 4 == 0) ; // isLeap
uint seconds = (uint)(time - n * DAYSECS) ;
uint minutes = seconds / 60 ;
uint hours = minutes / 60 ;
dt_struct.year = (int)(Y - 32800 + J) ;
dt_struct.mon = (int)(J ? M - 12 : M) ;
dt_struct.day = (int)(D + 1) ;
dt_struct.hour = (int)(hours) ;
dt_struct.min = (int)(minutes - (hours * 60));
dt_struct.sec = (int)(seconds - (minutes * 60));
dt_struct.day_of_week = (int)((n + 4) % 7U);
dt_struct.day_of_year = (int)(h + (J ? -MARCH1_BASED_DOY : 59 + l));
return (true);
}
//+==================================================================+
//| Extract Components of datetime: Sunday, yyyy.mm.dd hh:mm:ss |
//| Get() Units |
//+==================================================================+
int Second(void) { return Second(TimeTradeServer()); } // gets current second (0..59)
int Minute(void) { return Minute(TimeTradeServer()); } // gets current minute (0..59)
int Hour(void) { return Hour(TimeTradeServer()); } // gets current hour (0..23)
int Day(void) { return Day(TimeTradeServer()); } // gets day of current month (1..31)
int Month(void) { return Month(TimeTradeServer()); } // gets current month (1..12)
int Year(void) { return Year(TimeTradeServer()); } // gets current year (1970..3000)
int DayOfWeek(void) { return DayOfWeek(TimeTradeServer()); } // gets day of current week (0..6)
int DayOfYear(void) { return DayOfYear(TimeTradeServer()); } // gets day of current year (0..365)
//+------------------------------------------------------------------+
//| Return seconds of minute as integer (0..59) |
//+------------------------------------------------------------------+
int Second(const datetime t)
{
return (int)(t % MINSECS);
}
//+------------------------------------------------------------------+
//| Return minutes of hour as integer (0..59) |
//+------------------------------------------------------------------+
int Minute(const datetime t)
{
return (int)((t / MINSECS) % MINSECS);
}
//+------------------------------------------------------------------+
//| Return hour of day as integer (0..23) |
//+------------------------------------------------------------------+
int Hour(const datetime t)
{
return (int)((t / HOURSECS) % 24U);
}
//+------------------------------------------------------------------+
//| Return day of month as integer (1..31) |
//+------------------------------------------------------------------+
int Day(const datetime t)
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.day);
uint dayOfCentury = ((((uint)(t / DAYSECS) + DAYS_TO_1970 + MARCH1_BASED_DOY) << 2) | 3U) % DAYS_PER_400_YEARS;
uint daySinceMarch1 = (dayOfCentury | 3U) % DAYS_PER_4_YEARS / 4;
uint monthDayPacked = daySinceMarch1 * 2141 + 197913;
return (int)((monthDayPacked & 0xFFFF) / 2141) + 1;
}
//+------------------------------------------------------------------+
//| Return the month number as integer (1..12) |
//+------------------------------------------------------------------+
int Month(const datetime t)
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.mon);
uint dayOfCentury = ((((uint)(t / DAYSECS) + DAYS_TO_1970 + MARCH1_BASED_DOY) << 2) | 3U) % DAYS_PER_400_YEARS;
uint daySinceMarch1 = (dayOfCentury | 3U) % DAYS_PER_4_YEARS / 4;
uint monthDayPacked = daySinceMarch1 * 2141 + 197913;
return (int)(monthDayPacked >> 16) - (daySinceMarch1 >= MARCH1_BASED_DOY ? 12 : 0);
}
//+------------------------------------------------------------------+
//| Return the year as integer (1970..3000) |
//+------------------------------------------------------------------+
int Year(const datetime t)
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.year);
uint days = ((((uint)(t / DAYSECS) + DAYS_TO_1970) << 2) | 3U);
uint century = days / DAYS_PER_400_YEARS;
uint year = ((days % DAYS_PER_400_YEARS) | 3U) / DAYS_PER_4_YEARS;
return (int)(100 * century + year) + 1;
}
//+------------------------------------------------------------------+
//| Return the date part for the given date. |
//+------------------------------------------------------------------+
datetime DateOnly(const datetime t)
{
return StartOfDay(t);
}
//+------------------------------------------------------------------+
//| Return the time part for the given date. |
//+------------------------------------------------------------------+
datetime TimeOnly(const datetime t)
{
return (datetime)SecsElapsedOfDay(t);
}
//+==================================================================+
//| Day() Numbering |
//+==================================================================+
//+------------------------------------------------------------------+
//| Day of the week as integer (0 = Sunday to 6 = Saturday) |
//+------------------------------------------------------------------+
int DayOfWeek(const datetime t)
{
return (int)((t / DAYSECS + THURSDAY) % 7U); // 1 Jan 1970 is Thursday
}
//+------------------------------------------------------------------+
//| Returns the zero-based day of the year as integer (0...365) |
//+------------------------------------------------------------------+
int DayOfYear(const datetime t)
{
return (int)(((((((uint)(t / DAYSECS) + DAYS_TO_1970) << 2) | 3U) % DAYS_PER_400_YEARS) | 3U) % DAYS_PER_4_YEARS) >> 2;
}
//+==================================================================+
//| Quarter of Year |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the year quarter number (1..4). |
//+------------------------------------------------------------------+
int Quarter(const datetime t)
{
return ((Month(t) - 1) / 3) + 1;
}
//+==================================================================+
//| Epoch-Based Indices |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns the zero-based minute index since 1970-01-01 00:00. |
//+------------------------------------------------------------------+
int MinuteIndex(const datetime t)
{
return (int)(t / MINSECS);
}
//+------------------------------------------------------------------+
//| Returns the zero-based hour index since 1970-01-01 00:00. |
//+------------------------------------------------------------------+
int HourIndex(const datetime t)
{
return (int)(t / HOURSECS);
}
//+------------------------------------------------------------------+
//| Returns the zero-based day index since 1970-01-01. |
//| Useful for indicators to determine the first bar of the new day: |
//| bool NewDay = DayIndex(time[i]) != DayIndex(time[i-1]); |
//+------------------------------------------------------------------+
int DayIndex(const datetime t)
{
return (int)(t / DAYSECS);
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar week index since the week |
//| containing 1970-01-01. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeekIndex(const datetime t)
{
return (int)((t + WEEK_OFFSET) / WEEKSECS);
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar month index since 1970-01. |
//+------------------------------------------------------------------+
int MonthIndex(const datetime t)
{
return (Year(t) - 1970) * 12 + Month(t) - 1;
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar quarter index since 1970 Q1. |
//+------------------------------------------------------------------+
int QuarterIndex(const datetime t)
{
return (Year(t) - 1970) * 4 + Quarter(t) - 1;
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar year index since 1970. |
//+------------------------------------------------------------------+
int YearIndex(const datetime t)
{
return Year(t) - 1970;
}
//+==================================================================+
//| HourOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Hours elapsed from the start of week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int HourOfWeek(const datetime t)
{
return (int)(SecsElapsedOfWeek(t) / HOURSECS);
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int HourOfMonth(const datetime t)
{
return (int)(SecsElapsedOfMonth(t) / HOURSECS);
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int HourOfQuarter(const datetime t)
{
return (int)(SecsElapsedOfQuarter(t) / HOURSECS);
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int HourOfYear(const datetime t)
{
return (int)(SecsElapsedOfYear(t) / HOURSECS);
}
//+==================================================================+
//| MinuteOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int MinuteOfDay(const datetime t)
{
return (int)(SecsElapsedOfDay(t) / MINSECS);
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int MinuteOfWeek(const datetime t)
{
return (int)(SecsElapsedOfWeek(t) / MINSECS);
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int MinuteOfMonth(const datetime t)
{
return (int)(SecsElapsedOfMonth(t) / MINSECS);
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int MinuteOfQuarter(const datetime t)
{
return (int)(SecsElapsedOfQuarter(t) / MINSECS);
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int MinuteOfYear(const datetime t)
{
return (int)(SecsElapsedOfYear(t) / MINSECS);
}
//+==================================================================+
//| SecsElapsedOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of minute for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfMinute(const datetime t)
{
return (int)(t % MINSECS);
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of hour for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfHour(const datetime t)
{
return (int)(t % HOURSECS);
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfDay(const datetime t)
{
return (int)(t % DAYSECS);
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int SecondsSinceMidnight(const datetime t)
{
return (int)(t % DAYSECS);
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int SecsElapsedOfWeek(const datetime t)
{
return (int)((t + WEEK_OFFSET) % WEEKSECS);
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfMonth(const datetime t)
{
return (int)(t - StartOfMonth(t));
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfQuarter(const datetime t)
{
return (int)(t - StartOfQuarter(t));
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfYear(const datetime t)
{
return (int)(t - StartOfYear(t));
}
//+------------------------------------------------------------------+
//| Seconds elapsed since 1 Jan 1970 (Unix epoch) for the given date.|
//+------------------------------------------------------------------+
long SecsElapsedOfEpoch(const datetime t)
{
return (long)(t);
}
//####################################################################
//# #
//# Adjusters / Navigation #
//# #
//####################################################################
//+==================================================================+
//| StartOf() / FloorTo() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the start of a minute for the given date. |
//+------------------------------------------------------------------+
datetime StartOfMinute(const datetime t)
{
return t - (t % MINSECS);
}
//+------------------------------------------------------------------+
//| Return the start of an hour for the given date. |
//+------------------------------------------------------------------+
datetime StartOfHour(const datetime t)
{
return t - (t % HOURSECS);
}
//+------------------------------------------------------------------+
//| Return the start of a day for the given date. |
//+------------------------------------------------------------------+
datetime StartOfDay(const datetime t)
{
return t - (t % DAYSECS);
}
//+------------------------------------------------------------------+
//| Returns the start of the calendar week containing the given |
//| date/time. The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime StartOfWeek(const datetime t)
{
return t - ((t + WEEK_OFFSET) % WEEKSECS);
}
//+------------------------------------------------------------------+
//| Return the first day of a month for the given date. |
//+------------------------------------------------------------------+
datetime StartOfMonth(const datetime t)
{
const int y = Year(t);
const int m = Month(t);
return DateFrom(y, m, 1);
}
//+------------------------------------------------------------------+
//| Return the first day of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime StartOfQuarter(const datetime t)
{
const int y = Year(t);
const int m = Month(t);
const int qMonth = ((m - 1) / 3) * 3 + 1;
return DateFrom(y, qMonth, 1);
}
//+------------------------------------------------------------------+
//| Return the first day of a year for the given date. |
//+------------------------------------------------------------------+
datetime StartOfYear(const datetime t)
{
const int y = Year(t);
return DateFrom(y, 1, 1);
}
//+------------------------------------------------------------------+
//| Return the start second of today on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfToday(void)
{
return StartOfDay(TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Return the start second of tomorrow on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfTomorrow(void)
{
return AddDays(StartOfDay(TimeTradeServer()), 1);
}
//+------------------------------------------------------------------+
//| Return the start second of yesterday on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfYesterday(void)
{
return SubDays(StartOfDay(TimeTradeServer()), 1);
}
//+==================================================================+
//| EndOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the last second of a minute for the given date. |
//+------------------------------------------------------------------+
datetime EndOfMinute(const datetime t)
{
return StartOfMinute(t) + (MINSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last second of an hour for the given date. |
//+------------------------------------------------------------------+
datetime EndOfHour(const datetime t)
{
return StartOfHour(t) + (HOURSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last second of a day for the given date. |
//+------------------------------------------------------------------+
datetime EndOfDay(const datetime t)
{
return StartOfDay(t) + (DAYSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last second of a week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime EndOfWeek(const datetime t)
{
return StartOfWeek(t) + (WEEKSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last second of a month for the given date. |
//+------------------------------------------------------------------+
datetime EndOfMonth(const datetime t)
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// dt.day = DaysInMonth(dt.year, dt.mon);
// dt.hour = 23;
// dt.min = 59;
// dt.sec = 59;
// return(StructToTimeFast(dt));
int y = Year(t);
int m = Month(t);
m = (m % 12) + 1;
y += (m == 1);
return DateFrom(y, m, 1) - 1;
}
//+------------------------------------------------------------------+
//| Return the last second of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime EndOfQuarter(const datetime t)
{
return EndOfMonth(AddMonths(StartOfQuarter(t), 2));
}
//+------------------------------------------------------------------+
//| Return the last second of a year for the given date. |
//+------------------------------------------------------------------+
datetime EndOfYear(const datetime t)
{
const int y = Year(t);
return DateFrom((y + 1), 1, 1) - 1;
}
//+------------------------------------------------------------------+
//| Return the last second of today on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfToday(void)
{
return EndOfDay(TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Return the last second of tomorrow on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfTomorrow(void)
{
return AddDays(EndOfDay(TimeTradeServer()), 1);
}
//+------------------------------------------------------------------+
//| Return the last second of yesterday on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfYesterday(void)
{
return SubDays(EndOfDay(TimeTradeServer()), 1);
}
//+==================================================================+
//| LastDayOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the last day of a week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime LastDayOfWeek(const datetime t)
{
return EndOfWeek(t) - (DAYSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last day of a month for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfMonth(const datetime t)
{
return EndOfMonth(t) - (DAYSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last day of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfQuarter(const datetime t)
{
return EndOfQuarter(t) - (DAYSECS - 1);
}
//+------------------------------------------------------------------+
//| Return the last day of a year for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfYear(const datetime t)
{
return EndOfYear(t) - (DAYSECS - 1);
}
//+==================================================================+
//| RoundTo() / Nearest() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest minute. |
//+------------------------------------------------------------------+
datetime RoundToMinute(const datetime t)
{
return StartOfMinute(t + MINSECS / 2);
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest hour. |
//+------------------------------------------------------------------+
datetime RoundToHour(const datetime t)
{
return StartOfHour(t + HOURSECS / 2);
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest day. |
//+------------------------------------------------------------------+
datetime RoundToDay(const datetime t)
{
return StartOfDay(t + DAYSECS / 2);
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest week. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime RoundToWeek(const datetime t)
{
return StartOfWeek(t + WEEKSECS / 2);
}
//+==================================================================+
//| CeilTo() / Next() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Rounds up the given date to the next minute. |
//+------------------------------------------------------------------+
datetime CeilToMinute(const datetime t)
{
return StartOfMinute(t + MINSECS - 1);
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next hour. |
//+------------------------------------------------------------------+
datetime CeilToHour(const datetime t)
{
return StartOfHour(t + HOURSECS - 1);
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next day. |
//+------------------------------------------------------------------+
datetime CeilToDay(const datetime t)
{
return StartOfDay(t + DAYSECS - 1);
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next week. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime CeilToWeek(const datetime t)
{
return StartOfWeek(t + WEEKSECS - 1);
}
//+==================================================================+
//| Next() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the next occurrence of a weekday after the given date. |
//+------------------------------------------------------------------+
datetime NextDayOfWeek(const datetime t,
const ENUM_DAY_OF_WEEK weekday = SUNDAY)
{
int delta = weekday - DayOfWeek(t);
if (delta <= 0)
delta += 7;
return AddDays(StartOfDay(t), delta);
}
//+------------------------------------------------------------------+
//| When is the next Sunday? |
//+------------------------------------------------------------------+
datetime NextSunday(const datetime t)
{
return NextDayOfWeek(t, SUNDAY);
}
//+------------------------------------------------------------------+
//| When is the next Monday? |
//+------------------------------------------------------------------+
datetime NextMonday(const datetime t)
{
return NextDayOfWeek(t, MONDAY);
}
//+------------------------------------------------------------------+
//| When is the next Tuesday? |
//+------------------------------------------------------------------+
datetime NextTuesday(const datetime t)
{
return NextDayOfWeek(t, TUESDAY);
}
//+------------------------------------------------------------------+
//| When is the next Wednesday? |
//+------------------------------------------------------------------+
datetime NextWednesday(const datetime t)
{
return NextDayOfWeek(t, WEDNESDAY);
}
//+------------------------------------------------------------------+
//| When is the next Thursday? |
//+------------------------------------------------------------------+
datetime NextThursday(const datetime t)
{
return NextDayOfWeek(t, THURSDAY);
}
//+------------------------------------------------------------------+
//| When is the next Friday? |
//+------------------------------------------------------------------+
datetime NextFriday(const datetime t)
{
return NextDayOfWeek(t, FRIDAY);
}
//+------------------------------------------------------------------+
//| When is the next Saturday? |
//+------------------------------------------------------------------+
datetime NextSaturday(const datetime t)
{
return NextDayOfWeek(t, SATURDAY);
}
//+==================================================================+
//| Previous() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the previous occurrence of a weekday before the given date. |
//+------------------------------------------------------------------+
datetime PreviousDayOfWeek(const datetime t,
const ENUM_DAY_OF_WEEK weekday = SUNDAY)
{
int delta = DayOfWeek(t) - weekday;
if (delta <= 0)
delta += 7;
return SubDays(StartOfDay(t), delta);
}
//+------------------------------------------------------------------+
//| When is the previous Sunday? |
//+------------------------------------------------------------------+
datetime PreviousSunday(const datetime t)
{
return PreviousDayOfWeek(t, SUNDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Monday? |
//+------------------------------------------------------------------+
datetime PreviousMonday(const datetime t)
{
return PreviousDayOfWeek(t, MONDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Tuesday? |
//+------------------------------------------------------------------+
datetime PreviousTuesday(const datetime t)
{
return PreviousDayOfWeek(t, TUESDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Wednesday? |
//+------------------------------------------------------------------+
datetime PreviousWednesday(const datetime t)
{
return PreviousDayOfWeek(t, WEDNESDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Thursday? |
//+------------------------------------------------------------------+
datetime PreviousThursday(const datetime t)
{
return PreviousDayOfWeek(t, THURSDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Friday? |
//+------------------------------------------------------------------+
datetime PreviousFriday(const datetime t)
{
return PreviousDayOfWeek(t, FRIDAY);
}
//+------------------------------------------------------------------+
//| When is the previous Saturday? |
//+------------------------------------------------------------------+
datetime PreviousSaturday(const datetime t)
{
return PreviousDayOfWeek(t, SATURDAY);
}
//+==================================================================+
//| Nth() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the Nth weekday of the given year and month. |
//| |
//| Nth > 0 : 1 = first, 2 = second, ... |
//| Nth < 0 : -1 = last, -2 = second last, ... |
//| Returns 0 if the requested occurrence does not exist. |
//+------------------------------------------------------------------+
datetime NthWeekdayOfYearMonth(const int year,
const int month,
const int Nth,
const ENUM_DAY_OF_WEEK weekday = SUNDAY)
{
if(Nth == 0 || month < 1 || month > 12)
return 0;
const datetime first = DateFrom(year, month, 1);
const datetime last = DateFrom(year, month, DaysInMonth(year, month));
int jumpdays = (MathAbs(Nth) - 1) * 7;
if(Nth > 0)
{
// Count from the beginning of the month.
jumpdays += (7 + weekday - DayOfWeek(first)) % 7;
datetime result = AddDays(first, jumpdays);
return (result <= last) ? result : 0;
}
else
{
// Count from the end of the month.
jumpdays += (7 - weekday + DayOfWeek(last)) % 7;
datetime result = SubDays(last, jumpdays);
return (result >= first) ? result : 0;
}
}
//+------------------------------------------------------------------+
//| Return the first weekday of the month. |
//+------------------------------------------------------------------+
datetime FirstWeekdayOfMonth(const datetime t,
const ENUM_DAY_OF_WEEK weekday = SUNDAY)
{
return NthWeekdayOfYearMonth(Year(t), Month(t), 1, weekday);
}
//+------------------------------------------------------------------+
//| Return the last weekday of the month. |
//+------------------------------------------------------------------+
datetime LastWeekdayOfMonth(const datetime t,
const ENUM_DAY_OF_WEEK weekday = SUNDAY)
{
return NthWeekdayOfYearMonth(Year(t),Month(t),-1,weekday);
}
//+==================================================================+
//| WithXxx() / Replace() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the second updated. |
//+------------------------------------------------------------------+
datetime WithSecond(const datetime t, const int second)
{
if(second < 0 || second > 59)
return -1;
return AddSeconds(t, second - Second(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the minute updated. |
//+------------------------------------------------------------------+
datetime WithMinute(const datetime t, const int minute)
{
if(minute < 0 || minute > 59)
return -1;
return AddMinutes(t, minute - Minute(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the hour updated. |
//+------------------------------------------------------------------+
datetime WithHour(const datetime t, const int hour)
{
if(hour < 0 || hour > 23)
return -1;
return AddHours(t, hour - Hour(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the day of month updated.|
//+------------------------------------------------------------------+
datetime WithDay(const datetime t, const int day)
{
if(day < 1 || day > DaysInMonth(Year(t), Month(t)))
return -1;
return AddDays(t, day - Day(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the month updated. |
//+------------------------------------------------------------------+
datetime WithMonth(const datetime t, const int month)
{
if(month < 1 || month > 12)
return -1;
return AddMonths(t, month - Month(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the year updated. |
//+------------------------------------------------------------------+
datetime WithYear(const datetime t, const int year)
{
if(year < 1970 || year > 3000)
return -1;
return AddYears(t, year - Year(t));
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime adjusted to the specified |
//| weekday within the current week, preserving the time of day. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
datetime WithDayOfWeek(const datetime t,
const ENUM_DAY_OF_WEEK weekday)
{
const int first = (int)TIMEUTILS_FIRST_DAY_OF_WEEK;
const int current = DayOfWeek(t);
int delta = (int)weekday - current;
if((int)weekday < first)
delta += 7;
if(current < first)
delta -= 7;
return AddDays(t, delta);
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified time, |
//| preserving the date (i.e., replace time). |
//+------------------------------------------------------------------+
datetime WithTime(const datetime t,
const int hour,
const int minute,
const int second)
{
if(hour < 0 || hour > 23 ||
minute < 0 || minute > 59 ||
second < 0 || second > 59)
return -1;
datetime res = t;
res = WithHour(res, hour);
res = WithMinute(res, minute);
return WithSecond(res, second);
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified date, |
//| preserving the time of day (i.e., replace date). |
//+------------------------------------------------------------------+
datetime WithDate(const datetime t,
const int year,
const int month,
const int day)
{
MqlDateTime dt;
TimeToStructFast(t, dt);
if(year < 1970 || year > 3000 ||
month < 1 || month > 12 ||
day < 1 || day > DaysInMonth(year, month))
return -1;
dt.year = year;
dt.mon = month;
dt.day = day;
return StructToTimeFast(dt);
}
//####################################################################
//# #
//# Addition and Subtraction #
//# #
//####################################################################
//+==================================================================+
//| Add() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Add the specified number of seconds to the given date. |
//+------------------------------------------------------------------+
datetime AddSeconds(const datetime t, const int amount)
{
return t + amount;
}
//+------------------------------------------------------------------+
//| Add the specified number of minutes to the given date. |
//+------------------------------------------------------------------+
datetime AddMinutes(const datetime t, const int amount)
{
return t + ((datetime)amount * MINSECS);
}
//+------------------------------------------------------------------+
//| Add the specified number of hours to the given date. |
//+------------------------------------------------------------------+
datetime AddHours(const datetime t, const int amount)
{
return t + ((datetime)amount * HOURSECS);
}
//+------------------------------------------------------------------+
//| Add the specified number of days to the given date. |
//+------------------------------------------------------------------+
datetime AddDays(const datetime t, const int amount)
{
return t + ((datetime)amount * DAYSECS);
}
//+------------------------------------------------------------------+
//| Add the specified number of business days (Mon - Fri) to the |
//| given date, ignoring weekends. |
//+------------------------------------------------------------------+
datetime AddBusinessDays(const datetime t, const int amount)
{
int step = amount < 0 ? -1 : 1;
int fullWeeks = amount / 5;
int remaining = MathAbs(amount) % 5;
datetime t_end = AddDays(t, fullWeeks * 7);
// Loop over remaining business days
while(remaining > 0)
{
t_end = AddDays(t_end, step);
if(IsWeekday(t_end))
{
remaining--;
}
}
// If we add amount and land on a weekend, we add/reduce days
// to land on the next business day.
if(amount != 0)
{
if(IsSaturday(t_end))
t_end = AddDays(t_end, (step < 0 ? 2 : -1));
else if(IsSunday(t_end))
t_end = AddDays(t_end, (step < 0 ? 1 : -2));
}
return t_end;
}
//+------------------------------------------------------------------+
//| Add the specified number of weeks to the given date. |
//+------------------------------------------------------------------+
datetime AddWeeks(const datetime t, const int amount)
{
return t + ((datetime)amount * WEEKSECS);
}
//+------------------------------------------------------------------+
//| Add the specified number of months to the given date. |
//+------------------------------------------------------------------+
datetime AddMonths(const datetime t, const int amount)
{
MqlDateTime dt;
TimeToStructFast(t, dt);
int totalMonths = dt.year * 12 + (dt.mon - 1) + amount; // month is 1-based
dt.year = totalMonths / 12;
dt.mon = (totalMonths % 12) + 1;
dt.day = MathMin(dt.day, DaysInMonth(dt.year, dt.mon));
return StructToTimeFast(dt);
}
//+------------------------------------------------------------------+
//| Add the specified number of year quarters to the given date. |
//+------------------------------------------------------------------+
datetime AddQuarters(const datetime t, const int amount)
{
return AddMonths(t, amount * 3);
}
//+------------------------------------------------------------------+
//| Add the specified number of years to the given date. |
//+------------------------------------------------------------------+
datetime AddYears(const datetime t, const int amount)
{
return AddMonths(t, amount * 12);
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified |
//| calendar period added. The period is expressed in calendar |
//| years, months, days, hours, minutes, and seconds. |
//| |
//| For periods returned by CalendarDifference(), |
//| AddPeriod(from, period) reconstructs the original end date. |
//+------------------------------------------------------------------+
datetime AddPeriod(const datetime t,
const MqlDateTime& calendarPeriod)
{
if(calendarPeriod.year < 0)
return -1;
if(calendarPeriod.mon < 0 || calendarPeriod.mon > 11)
return -1;
if(calendarPeriod.day < 0)
return -1;
if(calendarPeriod.hour < 0 || calendarPeriod.hour > 23)
return -1;
if(calendarPeriod.min < 0 || calendarPeriod.min > 59)
return -1;
if(calendarPeriod.sec < 0 || calendarPeriod.sec > 59)
return -1;
datetime res = t;
res = AddMonths(res, calendarPeriod.year * 12 + calendarPeriod.mon);
res = AddDays(res, calendarPeriod.day);
res = AddHours(res, calendarPeriod.hour);
res = AddMinutes(res, calendarPeriod.min);
res = AddSeconds(res, calendarPeriod.sec);
return res;
}
//+==================================================================+
//| Sub() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Subtract the specified number of seconds from the given date. |
//+------------------------------------------------------------------+
datetime SubSeconds(const datetime t, const int amount)
{
return AddSeconds(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of minutes from the given date. |
//+------------------------------------------------------------------+
datetime SubMinutes(const datetime t, const int amount)
{
return AddMinutes(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of hours from the given date. |
//+------------------------------------------------------------------+
datetime SubHours(const datetime t, const int amount)
{
return AddHours(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of days from the given date. |
//+------------------------------------------------------------------+
datetime SubDays(const datetime t, const int amount)
{
return AddDays(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of business days (mon - fri) |
//| from the given date, ignoring weekends. |
//+------------------------------------------------------------------+
datetime SubBusinessDays(const datetime t, const int amount)
{
return AddBusinessDays(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of weeks from the given date. |
//+------------------------------------------------------------------+
datetime SubWeeks(const datetime t, const int amount)
{
return AddWeeks(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of months from the given date. |
//+------------------------------------------------------------------+
datetime SubMonths(const datetime t, const int amount)
{
return AddMonths(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of quarters from the given date. |
//+------------------------------------------------------------------+
datetime SubQuarters(const datetime t, const int amount)
{
return AddQuarters(t, -amount);
}
//+------------------------------------------------------------------+
//| Subtract the specified number of years from the given date. |
//+------------------------------------------------------------------+
datetime SubYears(const datetime t, const int amount)
{
return AddYears(t, -amount);
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified |
//| calendar period subtracted. The period is expressed in calendar |
//| years, months, days, hours, minutes, and seconds. |
//| |
//| This function performs the inverse calendar operation of |
//| AddPeriod(), applying the period in reverse order. |
//| |
//| Note that calendar arithmetic is generally not invertible due |
//| to month-end clamping and varying month lengths. Therefore, for |
//| periods returned by CalendarDifference(), |
//| |
//| AddPeriod(from, period) == to |
//| |
//| is guaranteed, but |
//| |
//| SubPeriod(to, period) == from |
//| |
//| is not guaranteed in all cases. |
//+------------------------------------------------------------------+
datetime SubPeriod(const datetime t,
const MqlDateTime& calendarPeriod)
{
if(calendarPeriod.year < 0)
return -1;
if(calendarPeriod.mon < 0 || calendarPeriod.mon > 11)
return -1;
if(calendarPeriod.day < 0)
return -1;
if(calendarPeriod.hour < 0 || calendarPeriod.hour > 23)
return -1;
if(calendarPeriod.min < 0 || calendarPeriod.min > 59)
return -1;
if(calendarPeriod.sec < 0 || calendarPeriod.sec > 59)
return -1;
datetime res = t;
res = AddSeconds(res, -calendarPeriod.sec);
res = AddMinutes(res, -calendarPeriod.min);
res = AddHours(res, -calendarPeriod.hour);
res = AddDays(res, -calendarPeriod.day);
res = AddMonths(res, -(calendarPeriod.year * 12 + calendarPeriod.mon));
return res;
}
//####################################################################
//# #
//# Difference #
//# #
//####################################################################
//+==================================================================+
//| DifferenceIn() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns the difference in the calendar day numbers between two |
//| date/time values, ignoring the time-of-day components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarDays(const datetime from, const datetime to)
{
return DayIndex(to) - DayIndex(from);
}
//+------------------------------------------------------------------+
//| Returns the difference between the calendar week indices of |
//| two date/time values, ignoring the time-of-day components. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int DifferenceInCalendarWeeks(const datetime from, const datetime to)
{
return WeekIndex(to) - WeekIndex(from);
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar month numbers between |
//| two dates, ignoring the day and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarMonths(const datetime from, const datetime to)
{
return MonthIndex(to) - MonthIndex(from);
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar quarter numbers between |
//| two dates, ignoring the month, day, and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarQuarters(const datetime from, const datetime to)
{
return QuarterIndex(to) - QuarterIndex(from);
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar year numbers between |
//| two dates, ignoring the month, day, and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarYears(const datetime from, const datetime to)
{
return YearIndex(to) - YearIndex(from);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed seconds between two dates. |
//+------------------------------------------------------------------+
long DifferenceInSeconds(const datetime from, const datetime to)
{
return (long)(to - from);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed minutes between two dates. |
//+------------------------------------------------------------------+
int DifferenceInMinutes(const datetime from, const datetime to)
{
return (int)((to - from) / (int)MINSECS);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed hours between two dates. |
//+------------------------------------------------------------------+
int DifferenceInHours(const datetime from, const datetime to)
{
return (int)((to - from) / (int)HOURSECS);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed 24-hour periods between two dates. |
//+------------------------------------------------------------------+
int DifferenceInDays(const datetime from, const datetime to)
{
return (int)((to - from) / (int)DAYSECS);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full weeks between two dates. |
//+------------------------------------------------------------------+
int DifferenceInWeeks(const datetime from, const datetime to)
{
return (int)((to - from) / (int)WEEKSECS);
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full months between two dates. |
//+------------------------------------------------------------------+
// DifferenceInCale DifferenceInMont |
// | From | To | ndarMonths | hs |
// |-------------|-------------|----------------: |----------------: |
// | Jan 15 | Feb 14 | 1 | 0 |
// | Jan 15 | Feb 15 | 1 | 1 |
// | Jan 31 | Feb 28 | 1 | 1 |
// | Jan 31 | Mar 30 | 2 | 1 |
// | Jan 31 | Mar 31 | 2 | 2 |
// | Feb 29 2024 | Feb 27 2025 | 12 | 11 |
// | Feb 29 2024 | Feb 28 2025 | 12 | 12 |
//+------------------------------------------------------------------+
int DifferenceInMonths(const datetime from, const datetime to)
{
if(from > to)
return -DifferenceInMonths(to, from);
int months = DifferenceInCalendarMonths(from, to);
// https://github.com/dateutil/dateutil/blob/master/src/dateutil/relativedelta.py#L153
// add months back. If we've overshot our target, make an adjustment
return AddMonths(from, months) <= to ? months : months - 1;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full quarters between dates. |
//+------------------------------------------------------------------+
int DifferenceInQuarters(const datetime from, const datetime to)
{
return DifferenceInMonths(from, to) / 3;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full years between two dates. |
//+------------------------------------------------------------------+
int DifferenceInYears(const datetime from, const datetime to)
{
return DifferenceInMonths(from, to) / 12;
}
//+------------------------------------------------------------------+
//| Return the number of business days (Mon-Fri) in the half-open |
//| interval [from, to), excluding weekends. |
//+------------------------------------------------------------------+
int DifferenceInBusinessDays(const datetime from, const datetime to)
{
int totalDays = DifferenceInCalendarDays(from, to);
int step = totalDays < 0 ? -1 : 1;
if(totalDays == 0)
return 0;
int fullWeeks = totalDays / 7;
int business = fullWeeks * 5;
int remaining = MathAbs(totalDays) % 7;
datetime dt_temp = from;
// Loop over remaining days not part of a full week
for(int i = 0; i < remaining; i++)
{
if(IsWeekday(dt_temp))
{
business += step;
}
dt_temp = AddDays(dt_temp, step);
}
return business;
}
//+------------------------------------------------------------------+
//| Return the number of weekend days in the half-open interval |
//| [from, to). The end date is not included. |
//+------------------------------------------------------------------+
int DifferenceInWeekendDays(const datetime from, const datetime to)
{
return DifferenceInCalendarDays(from, to)
- DifferenceInBusinessDays(from, to);
}
//+------------------------------------------------------------------+
//| Returns the calendar difference between two dates, broken down |
//| into years, months, days, hours, minutes, and seconds. |
//+------------------------------------------------------------------+
bool CalendarDifference(datetime from, datetime to, MqlDateTime& diff)
{
const static MqlDateTime zero = {};
diff = zero;
if(from == to)
return(true);
if(from > to)
{
datetime temp = from;
from = to;
to = temp;
}
const int totalMonths = DifferenceInMonths(from, to);
diff.year = totalMonths / 12;
diff.mon = totalMonths % 12;
from = AddMonths(from, totalMonths);
diff.day = DifferenceInDays(from, to);
from = AddDays(from, diff.day);
diff.hour = DifferenceInHours(from, to);
from = AddHours(from, diff.hour);
diff.min = DifferenceInMinutes(from, to);
from = AddMinutes(from, diff.min);
diff.sec = (int)DifferenceInSeconds(from, to);
return (true);
}
//+------------------------------------------------------------------+
//| Returns the calendar difference between two dates as a |
//| human-readable string (e.g. "2y 3m 5d 04:12:30"). |
//+------------------------------------------------------------------+
string CalendarDifferenceToString(const datetime from, const datetime to)
{
if(from == to)
return "0y 0m 0d 00:00:00";
MqlDateTime diff;
CalendarDifference(from, to, diff);
string result = "";
result += IntegerToString(diff.year);
result += "y " + IntegerToString(diff.mon);
result += "m " + IntegerToString(diff.day);
result += "d " + IntegerToString(diff.hour, 2, '0');
result += ":" + IntegerToString(diff.min, 2, '0');
result += ":" + IntegerToString(diff.sec, 2, '0');
return result;
}
//####################################################################
//# #
//# Comparison and Checks #
//# #
//####################################################################
//+==================================================================+
//| Is() Checks |
//+==================================================================+
//+------------------------------------------------------------------+
//| Is the given date the first day of a month? |
//+------------------------------------------------------------------+
bool IsFirstDayOfMonth(const datetime t)
{
return Day(t) == 1;
}
//+------------------------------------------------------------------+
//| Is the given date the last day of a month? |
//+------------------------------------------------------------------+
bool IsLastDayOfMonth(const datetime t)
{
return EndOfDay(t) == EndOfMonth(t);
}
//+------------------------------------------------------------------+
//| Does the given date fall on a weekend? |
//+------------------------------------------------------------------+
bool IsWeekend(const datetime t)
{
int dow = DayOfWeek(t);
return dow == SATURDAY || dow == SUNDAY;
}
//+------------------------------------------------------------------+
//| Does the given date fall on a business day? |
//+------------------------------------------------------------------+
bool IsWeekday(const datetime t)
{
return !IsWeekend(t);
}
//+------------------------------------------------------------------+
//| Is the given date Sunday? |
//+------------------------------------------------------------------+
bool IsSunday(const datetime t)
{
return DayOfWeek(t) == SUNDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Monday? |
//+------------------------------------------------------------------+
bool IsMonday(const datetime t)
{
return DayOfWeek(t) == MONDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Tuesday? |
//+------------------------------------------------------------------+
bool IsTuesday(const datetime t)
{
return DayOfWeek(t) == TUESDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Wednesday? |
//+------------------------------------------------------------------+
bool IsWednesday(const datetime t)
{
return DayOfWeek(t) == WEDNESDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Thursday? |
//+------------------------------------------------------------------+
bool IsThursday(const datetime t)
{
return DayOfWeek(t) == THURSDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Friday? |
//+------------------------------------------------------------------+
bool IsFriday(const datetime t)
{
return DayOfWeek(t) == FRIDAY;
}
//+------------------------------------------------------------------+
//| Is the given date Saturday? |
//+------------------------------------------------------------------+
bool IsSaturday(const datetime t)
{
return DayOfWeek(t) == SATURDAY;
}
//+==================================================================+
//| IsSame() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same minute. |
//+------------------------------------------------------------------+
bool IsSameMinute(const datetime a, const datetime b)
{
return MinuteIndex(a) == MinuteIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same hour. |
//+------------------------------------------------------------------+
bool IsSameHour(const datetime a, const datetime b)
{
return HourIndex(a) == HourIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same day. |
//+------------------------------------------------------------------+
bool IsSameDay(const datetime a, const datetime b)
{
return DayIndex(a) == DayIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same week. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
bool IsSameWeek(const datetime a, const datetime b)
{
return WeekIndex(a) == WeekIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same month. |
//+------------------------------------------------------------------+
bool IsSameMonth(const datetime a, const datetime b)
{
return MonthIndex(a) == MonthIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same quarter |
//+------------------------------------------------------------------+
bool IsSameQuarter(const datetime a, const datetime b)
{
return QuarterIndex(a) == QuarterIndex(b);
}
//+------------------------------------------------------------------+
//| Check whether both date/time values fall within the same year. |
//+------------------------------------------------------------------+
bool IsSameYear(const datetime a, const datetime b)
{
return YearIndex(a) == YearIndex(b);
}
//+==================================================================+
//| IsCurrent() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Is the given date in the same minute as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentMinute(const datetime t)
{
return IsSameMinute(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date in the same hour as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentHour(const datetime t)
{
return IsSameHour(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date in the same week as the current server time |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
bool IsCurrentWeek(const datetime t)
{
return IsSameWeek(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date in the same month as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentMonth(const datetime t)
{
return IsSameMonth(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is this date in the same quarter (and year) as the server ? |
//+------------------------------------------------------------------+
bool IsCurrentQuarter(const datetime t)
{
return IsSameQuarter(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date in the same year as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentYear(const datetime t)
{
return IsSameYear(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date today on the trade server |
//+------------------------------------------------------------------+
bool IsToday(const datetime t)
{
return IsSameDay(t, TimeTradeServer());
}
//+------------------------------------------------------------------+
//| Is the given date tomorrow on the trade server |
//+------------------------------------------------------------------+
bool IsTomorrow(const datetime t)
{
return IsSameDay(t, AddDays(TimeTradeServer(), 1));
}
//+------------------------------------------------------------------+
//| Is the given date yesterday on the trade server |
//+------------------------------------------------------------------+
bool IsYesterday(const datetime t)
{
return IsSameDay(t, SubDays(TimeTradeServer(), 1));
}
//+==================================================================+
//| Session() Checks |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns true if the specified datetime falls within the |
//| specified recurring daily session [start, end). |
//| |
//| The session repeats every day at the same start and end times. |
//| |
//| If start <= end, the session occurs within a single day. |
//| If start > end, the session spans midnight into the next day. |
//+------------------------------------------------------------------+
bool IsInSession(const datetime t,
const int startHour,
const int startMinute,
const int endHour,
const int endMinute)
{
if(startHour < 0 || startHour > 23 ||
startMinute < 0 || startMinute > 59 ||
endHour < 0 || endHour > 23 ||
endMinute < 0 || endMinute > 59)
return false;
const int current = SecondsSinceMidnight(t);
const int start = startHour * HOURSECS + startMinute * MINSECS;
const int end = endHour * HOURSECS + endMinute * MINSECS;
return (start <= end)
? (current >= start && current < end)
: (current >= start || current < end);
}
//+------------------------------------------------------------------+
//| Returns true if the current server time falls within the |
//| specified recurring daily session [start, end). |
//+------------------------------------------------------------------+
bool IsInSession(const int startHour,
const int startMinute,
const int endHour,
const int endMinute)
{
return IsInSession(
TimeTradeServer(),
startHour,
startMinute,
endHour,
endMinute);
}
//+------------------------------------------------------------------+
//| Returns true if the current server time falls within the |
//| specified recurring daily session [start, end). |
//| |
//| Time strings must be in "HH:MM" or "HH:MM:SS" format. |
//+------------------------------------------------------------------+
bool IsInSession(const string startTime,
const string endTime)
{
const datetime start = DateFromString(startTime);
const datetime end = DateFromString(endTime);
return IsInSession(
TimeTradeServer(),
Hour(start),
Minute(start),
Hour(end),
Minute(end));
}
//+------------------------------------------------------------------+
//| Returns true if two half-open intervals [aStart, aEnd) and |
//| [bStart, bEnd) overlap. |
//| |
//| If an overlap exists, the overlapping interval is written to |
//| overlapStart and overlapEnd. |
//| |
//| If the intervals do not overlap, or either interval is invalid |
//| (end < start), returns false and sets both output values to 0. |
//+------------------------------------------------------------------+
bool SessionOverlap(const datetime aStart,
const datetime aEnd,
const datetime bStart,
const datetime bEnd,
datetime &overlapStart,
datetime &overlapEnd)
{
overlapStart = 0;
overlapEnd = 0;
if(aEnd < aStart || bEnd < bStart)
return false;
const datetime s = MathMax(aStart, bStart);
const datetime e = MathMin(aEnd, bEnd);
if(s >= e)
return false;
overlapStart = s;
overlapEnd = e;
return true;
}
//+==================================================================+
//| Misc |
//+==================================================================+
//+------------------------------------------------------------------+
//| Checks whether the given year is a leap year or not |
//+------------------------------------------------------------------+
bool IsLeapYear(const int year)
{
//return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
// From: https://www.youtube.com/watch?v=0s9F4QWAl-E&t=1790s
return (year & ((year % 100 != 0) ? 3 : 15)) == 0;
}
//+------------------------------------------------------------------+
//| Returns the number of days in a month of the given year. |
//+------------------------------------------------------------------+
int DaysInMonth(const int year, const int month)
{
//const int dim[13] = {0, 31, (IsLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//return dim[month % 13];
// From: https://www.youtube.com/watch?v=0s9F4QWAl-E&t=1790s
if(month == 2)
return 28 + IsLeapYear(year);
return 30 | (month ^ (month >> 3));
}
//+------------------------------------------------------------------+
//| Returns the number of days in a given year. |
//+------------------------------------------------------------------+
int DaysInYear(const int year)
{
return 365 + IsLeapYear(year);
}
//+==================================================================+
//| Week Utilities |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns the calendar week number of the month (1...6). |
//| |
//| Week 1 is the first calendar week containing the first day of |
//| the month. The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeekOfMonth(const datetime t)
{
return WeekIndex(t) - WeekIndex(StartOfMonth(t)) + 1;
}
//+------------------------------------------------------------------+
//| Returns the calendar week number of the year (1...54). |
//| |
//| Week 1 is the first calendar week containing January 1st. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeekOfYear(const datetime t)
{
return WeekIndex(t) - WeekIndex(StartOfYear(t)) + 1;
}
//+------------------------------------------------------------------+
//| Returns the number of calendar weeks spanned by the specified |
//| month. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeeksInMonth(const int year, const int month)
{
const datetime first = DateFrom(year, month, 1);
return WeekIndex(EndOfMonth(first)) - WeekIndex(first) + 1;
}
//+------------------------------------------------------------------+
//| Returns the number of calendar weeks spanned by the specified |
//| year. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeeksInYear(const int year)
{
const datetime first = DateFrom(year, 1, 1);
return WeekIndex(EndOfYear(first)) - WeekIndex(first) + 1;
}
//####################################################################
//# #
//# Format & Display #
//# #
//####################################################################
//+==================================================================+
//| Formating Time to String |
//+==================================================================+
//+------------------------------------------------------------------+
//| Format time with the weekday name => "Wed, 2023.02.14 01:59" |
//+------------------------------------------------------------------+
string t2s(const datetime t, const int mode = TIME_DATE | TIME_MINUTES)
{
const static string days[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
return days[ DayOfWeek(t) ] + ", " + TimeToString(t, mode);
}
//+------------------------------------------------------------------+
//| Format the time in seconds to a string (like 2d 14:58:04) |
//+------------------------------------------------------------------+
string SecondsToString(const int seconds)
{
const int days = (int)(seconds / DAYSECS);
const string d = days ? (string)days + "d " : "";
return d + TimeToString(seconds, TIME_SECONDS);
}
//+------------------------------------------------------------------+
//| Return the month name for a month number [1-12] |
//+------------------------------------------------------------------+
string MonthName(const int monthNo)
{
const static string months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
return (monthNo < 1 || monthNo > 12)
? "Undefined monthNo " + (string)monthNo : months[monthNo - 1];
}
//+------------------------------------------------------------------+
//| Return the weekday name for a weekday number [0-6] |
//+------------------------------------------------------------------+
string DayName(const int dayNo)
{
const static string days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
return (dayNo < 0 || dayNo > 6)
? "Undefined dayNo " + (string)dayNo : days[dayNo];
}
//+------------------------------------------------------------------+
//| Get the formatted time according to the passed string of tokens. |
//| List of all available formats: |
//| Format Output Description |
//| ------ ---------------- ------------------------------------- |
//| YY 18 Two-digit year |
//| YYYY 2018 Four-digit year |
//| M 1-12 The month, beginning at 1 |
//| MM 01-12 The month, 2-digits |
//| MMM Jan-Dec The abbreviated month name, 3-letters |
//| MMMM January-December The full month name |
//| D 1-31 The day of the month |
//| DD 01-31 The day of the month, 2-digits |
//| DDD Sun-Sat The short name of the day of the week |
//| DDDD Sunday-Saturday The name of the day of the week |
//| h 0-23 The hour |
//| hh 00-23 The hour, 2-digits |
//| H 1-12 The hour, 12-hour clock |
//| HH 01-12 The hour, 12-hour clock, 2-digits |
//| m 0-59 The minute |
//| mm 00-59 The minute, 2-digits |
//| s 0-59 The second |
//| ss 00-59 The second, 2-digits |
//| A AM PM |
//| a am pm |
//+------------------------------------------------------------------+
//| Sample formats: |
//| "YYYY.MM.DD hh:mm" // "2024.12.08 22:05" (default) |
//| "DDD, YYYY.MM.DD hh:mm:ss" // "Sun, 2024.12.08 22:05:21" |
//| "D MMMM YYYY, HH:mm a" // "8 December 2024, 10:05 pm" |
//| "DD/MM/YYYY" // "08/12/2024" |
//+------------------------------------------------------------------+
string TimeFormat(const datetime t,
const string format = "YYYY.MM.DD hh:mm") {
string retVal;
MqlDateTime dt_struct;
if(format == "" || StringLen(format) == 0) {
Print("invalid format");
return "";
}
if(TimeToStructFast(t, dt_struct) == false) {
Print("TimeToStructFast() failed. Error ", GetLastError());
return "";
}
string token = "";
int index_char = 0;
while (index_char < StringLen(format)) {
// get next token from format string
do {
token += StringSubstr(format, index_char, 1);
index_char++;
} while (index_char < StringLen(format) && format[index_char] == token[StringLen(token) - 1]);
// format datetime value based on format token
if(token == "YYYY") {
retVal += IntegerToString(dt_struct.year);
} else if(token == "YY") {
retVal += IntegerToString(dt_struct.year % 100, 2, '0');
} else if(token == "MMMM") {
retVal += MonthName(dt_struct.mon);
} else if(token == "MMM") {
retVal += StringSubstr(MonthName(dt_struct.mon), 0, 3);
} else if(token == "MM") {
retVal += IntegerToString(dt_struct.mon, 2, '0');
} else if(token == "M") {
retVal += IntegerToString(dt_struct.mon);
} else if(token == "DDDD") {
retVal += DayName(dt_struct.day_of_week);
} else if(token == "DDD") {
retVal += StringSubstr(DayName(dt_struct.day_of_week), 0, 3);
} else if(token == "DD") {
retVal += IntegerToString(dt_struct.day, 2, '0');
} else if(token == "D") {
retVal += IntegerToString(dt_struct.day);
} else if(token == "hh") {
retVal += IntegerToString(dt_struct.hour, 2, '0');
} else if(token == "h") {
retVal += IntegerToString(dt_struct.hour);
} else if(token == "HH") {
retVal += IntegerToString((bool)(dt_struct.hour % 12) ? dt_struct.hour % 12 : 12, 2, '0');
} else if(token == "H") {
retVal += IntegerToString((bool)(dt_struct.hour % 12) ? dt_struct.hour % 12 : 12);
} else if(token == "mm") {
retVal += IntegerToString(dt_struct.min, 2, '0');
} else if(token == "m") {
retVal += IntegerToString(dt_struct.min);
} else if(token == "ss") {
retVal += IntegerToString(dt_struct.sec, 2, '0');
} else if(token == "s") {
retVal += IntegerToString(dt_struct.sec);
} else if(token == "A") {
retVal += dt_struct.hour < 12 ? "AM" : "PM";
} else if(token == "a") {
retVal += dt_struct.hour < 12 ? "am" : "pm";
} else { // if there are any non-matching characters left in format string
retVal += token;
}
token = "";
}
return (retVal);
}
#undef DAYS_PER_4_YEARS
#undef DAYS_PER_400_YEARS
#undef DAYS_TO_1970
#undef MARCH1_BASED_DOY
#endif // #ifndef TIMEUTILS_UNIQUE_HEADER_ID_H
//+------------------------------------------------------------------+
/*
example code:
#include "TimeUtils.mqh"
void OnStart()
{
datetime t = TimeLocal();
Print( t2s(t, TIME_DATE|TIME_SECONDS) ); // Formats time with the weekday name
Print( Year(t) );
Print( Month(t) );
Print( Day(t) );
Print( Hour(t) );
Print( Minute(t) );
Print( Second(t) );
Print( DayOfWeek(t) );
Print( DayOfYear(t) );
MqlDateTime dt[1] = {};
TimeToStructFast(t, dt[0]);
ArrayPrint(dt);
dt[0].year += 1;
Print(StructToTimeFast(dt[0]));
}
example output:
Tue, 2024.12.03 20:46:58
2024
12
3
20
46
58
2
337
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2024 12 3 20 46 58 2 337
2025.12.03 20:46:58
*/
//+------------------------------------------------------------------+