Implementierung von praktischen Modulen aus anderen Sprachen in MQL5 (Teil 04): Zeit-, Datums- und Datetime-Module aus Python
Inhalt
- Einführung
- Die Zeitklasse
- Die Klasse der Zeitzoneninformationen
- Die Klasse Timedelta
- Das Objekt der Klasse date
- Das Modul datetime
- Schlussfolgerung
Einführung
Zeit ist eine grundlegende Einheit in unserem Leben; alles, was in diesem Universum existiert, wird in Zeit gemessen. In unserem täglichen Leben messen wir unsere Ziele und die Zeit, die wir zum Erreichen dieser Ziele benötigen, und wir stellen sogar enge Zeitpläne auf, um Aufgaben mit Zeiterfassungsgeräten wie Smartphones und Uhren zu messen (zu überwachen).
Im Bereich der Algorithmen und des Handels im Allgemeinen ist die Zeit immer noch eine entscheidende Größe. Wir treffen oft zeitbasierte Handelsentscheidungen und bewerten unsere Erfolge in der Regel auf täglicher, monatlicher und wöchentlicher Basis.
Die Programmiersprache MQL5 verfügt über zahlreiche integrierte Funktionen zur Verwaltung und Auswertung der Zeit, die sicherstellen, dass unsere algorithmischen Handelssysteme die Zeit in der realen Welt kennen und berücksichtigen. Unsere bevorzugte Programmiersprache bietet jedoch eine sehr grundlegende (einfache) und manchmal nicht leicht lesbare Art, mit Zeit, Datum usw. zu arbeiten, im Vergleich zu anderen Sprachen wie Python, die reichhaltige Module für diese Aufgabe bieten, wie datetime, calendar, time, zoneinfo usw.

In diesem Artikel werden wir ähnliche Module, wie sie in Python angeboten werden, für die Zeitverarbeitung in der Programmiersprache MQL5 implementieren.
Die Klasse Time (Modul)
Wir beginnen mit der Klasse der Zeit, die die grundlegenden Funktionen (Methoden) für die Arbeit mit der Zeit in der Programmiersprache Python enthält.
Laut einer Python-Dokumentation:
Ein Zeitobjekt stellt eine (lokale) Tageszeit dar, die unabhängig von einem bestimmten Tag ist und über ein tzinfo-Objekt angepasst werden kann.
class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
Alle Argumente sind optional. tzinfo kann None oder eine Instanz einer tzinfo-Unterklasse sein. Die übrigen Argumente müssen ganze Zahlen in den folgenden Bereichen sein:
- 0 <= Stunde < 24,
- 0 <= Minute < 60,
- 0 <= Sekunde < 60,
- 0 <= Mikrosekunde < 1000000
Wenn ein Argument außerhalb dieser Bereiche angegeben wird, wird ValueError ausgelöst. Alle sind standardmäßig auf 0 gesetzt, außer tzinfo, das standardmäßig auf None gesetzt ist.
Python bietet Klassen wie datetime und date mit ähnlichen Methoden für die Arbeit mit der Zeit. Die Klasse CTime aus einem Modul namens CTime ist jedoch nur für die Arbeit mit der Zeit zuständig (ohne das Datum zu kennen). So wenn Sie nur eine bestimmte Tageszeit wissen möchten.
Innerhalb einer Klasse mit dem Namen CTime müssen wir die Überprüfung der Werte handhaben, um sicherzustellen, dass der Nutzer im Klassenkonstruktor die richtigen Werte für die Erstellung eines Zeitobjekts angegeben hat, ähnlich wie es in Python geschieht.
class CTime { protected: uint m_hour; uint m_minute; uint m_second; uint m_millisecond; CTZInfo *m_tzinfo; public: //--- constructors CTime(void); CTime(const int hour, const int minute, const int second, CTZInfo *tzinfo=NULL, const int milliseconds=0); ~CTime(void); //--- A destructor
CTime::CTime(const int hour, const int minute, const int second, CTZInfo *tzinfo=NULL, const int milliseconds=0) { // --- Validate hour --- if(hour < MINHOUR || hour > MAXHOUR) { printf("CTime Error: hour (%d) out of range [%d..%d]. Defaulting to 0.", hour, MINHOUR, MAXHOUR); m_hour = 0; } else m_hour = hour; // --- Validate minute --- if(minute < MINMINUTES || minute > MAXMINUTES) { printf("CTime Error: minute (%d) out of range [%d..%d]. Defaulting to 0.", minute, MINMINUTES, MAXMINUTES); m_minute = 0; } else m_minute = minute; // --- Validate second --- if(second < MINSECOND || second > MAXSECOND) { printf("CTime Error: second (%d) out of range [%d..%d]. Defaulting to 0.", second, MINSECOND, MAXSECOND); m_second = 0; } else m_second = second; // --- Validate millisecond --- if(milliseconds < MINMILLISECOND || milliseconds > MAXMILLISECOND) { printf("CTime Error: millisecond (%d) out of range [%d..%d]. Defaulting to 0.", milliseconds, MINMILLISECOND, MAXMILLISECOND); m_millisecond = 0; } else m_millisecond = milliseconds; // --- Timezone info pointer --- m_tzinfo = tzinfo; }
Wenn ein Klassenkonstruktor mit optionalen Parametern aufgerufen wird, füllt er die Variablen innerhalb der Klasse auf und erzeugt so ein CTime-Objekt.
Eine optionale Variable namens tzinfo speichert die Informationen über eine bestimmte Zeitzone, zu der ein Zeitobjekt gehört.
Im Folgenden werden einige Methoden der Klasse CTime beschrieben.
(a): fromisoformat
Diese Funktion gibt ein CTime-Objekt zurück, das der Variablen time_string in einem beliebigen gültigen ISO 8601-Format entspricht, mit den folgenden Ausnahmen:
- Zeitzonenverschiebungen können Bruchteile von Sekunden haben.
- Das führende T, das normalerweise in Fällen erforderlich ist, in denen ein Datum und eine Uhrzeit nicht eindeutig zuzuordnen sind, ist nicht erforderlich.
- Bruchteile von Sekunden können eine beliebige Anzahl von Nachkommastellen haben (alles über 6 wird abgeschnitten).
- Bruchteile von Stunden und Minuten werden nicht unterstützt.
CTime CTime::fromisoformat(string time_string) Beispiel für die Verwendung:
void OnStart() { //--- CTime time; Print("Time: ",time.fromisoformat("04:23:01").__str__()); Print("Time: ",time.fromisoformat("T04:23:01").__str__()); Print("Time: ",time.fromisoformat("T042301").__str__()); Print("Time: ",time.fromisoformat("04:23:01.000384").__str__()); Print("Time: ",time.fromisoformat("04:23:01,000384").__str__()); Print("Time: ",time.fromisoformat("04:23:01+04:00").__str__()); Print("Time: ",time.fromisoformat("04:23:01Z").__str__()); Print("Time: ",time.fromisoformat("04:23:01+00:00").__datetime__()); }
Ausgabe:
OL 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 IG 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 KO 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 EF 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 GQ 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 QI 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 CP 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 04:23:01 HJ 0 20:44:38.611 Time testing (XAUUSD,H1) Time: 1970.01.01 04:23:01
Die Methoden __str__() und __datetime__() konvertieren die im CTime-Objekt gespeicherte Zeit in ein String- bzw. Datetime-Format (Variablen).
(b): strptime
Diese Funktion wandelt eine gegebene Zeit in einem String-Format in eine entsprechende Datetime-Variable um.
datetime CTime::strptime(string timestr, string format)
Beispiel für die Verwendung:
void OnStart() { //--- Print("Time: ", CTime::strptime("00:00:01", "%H:%M:%S")); Print("Time: ", CTime::strptime("00,00,01", "%H,%M,%S")); Print("Time: ", CTime::strptime("00-00-01", "%H-%M-%S")); }
Ausgabe:
MD 0 20:37:49.509 Time testing (XAUUSD,H1) Time: 1970.01.01 00:00:01 IL 0 20:37:49.509 Time testing (XAUUSD,H1) Time: 1970.01.01 00:00:01 EE 0 20:37:49.509 Time testing (XAUUSD,H1) Time: 1970.01.01 00:00:01
(c): replace
Diese Funktion gibt ein neues CTime-Objekt mit denselben Werten zurück, wobei die angegebenen Parameter aktualisiert wurden. Beachten Sie, dass tzinfo=NULL angegeben werden kann, um eine naive Zeit aus einer bekannten Zeit zu erstellen, ohne die Zeitdaten zu konvertieren.
CTime CTime::replace(const int hour, const int minute=-1, const int second=-1, CTZInfo *tzinfo=NULL, const int millisecond=0) { //--- Modify only specified values int n_hour = int(hour<=-1?this.m_hour:hour); int n_minute = int(minute<=-1?this.m_minute:minute); int n_second = int(second<=-1?this.m_second:second); int n_millisecond = int(millisecond<=-1?this.m_millisecond:millisecond); //--- m_tzinfo = tzinfo; return CTime(n_hour, n_minute, n_second, m_tzinfo, n_millisecond); }
Beispiel für die Verwendung:
void OnStart() { CTime time(9, 48, 10, &tzinfo); Print(time.__str__()); time = time.replace(22); //replace the hour and assign the new CTime object to the old one Print(time.__str__()); }
Ausgabe:
FR 0 11:05:16.339 Time testing (XAUUSD,H1) 09:48:10 IN 0 11:05:16.339 Time testing (XAUUSD,H1) 22:48:10
(c): isoformat
Diese Funktion gibt eine Zeichenkette zurück, die die Zeit im ISO 8601-Format darstellt, eine wie:
- HH:MM:SS.ffffff, wenn die Mikrosekunde nicht 0 ist
- HH:MM:SS, wenn die Mikrosekunde 0 ist
- HH:MM:SS.ffffff+HH:MM[:SS[.ffffff]], wenn utcoffset() nicht None zurückgibt
- HH:MM:SS+HH:MM[:SS[.ffffff]], wenn die Mikrosekunde 0 ist und utcoffset() nicht None zurückgibt
string CTime::isoformat(string timespec = "auto") { string hh = StringFormat("%02d", m_hour); string mm = StringFormat("%02d", m_minute); string ss = StringFormat("%02d", m_second); string ms = StringFormat("%03d", m_millisecond); // ----- Timespec switch ----- if(timespec == "hours") return hh; if(timespec == "minutes") return hh + ":" + mm; if(timespec == "seconds") return hh + ":" + mm + ":" + ss; if(timespec == "milliseconds") return hh + ":" + mm + ":" + ss + "." + ms; // ----- AUTO ----- // Python rule: include .mmm only if non-zero if(timespec == "auto") { if(m_millisecond > 0) return hh + ":" + mm + ":" + ss + "." + ms; else return hh + ":" + mm + ":" + ss; } // Invalid timespec -> fallback to full precision return hh + ":" + mm + ":" + ss + "." + ms; }
Das optionale Argument timespec gibt die Anzahl der zusätzlichen Komponenten der Zeit an, die einbezogen werden sollen (die Vorgabe ist 'auto'). Es kann einer der folgenden Punkte sein:
- 'auto': Wie 'auto' wenn Mikrosekunden 0 ist, sonst wie 'microseconds'.
- 'hours': Geben Sie die Stunde im zweistelligen HH-Format an.
- 'minutes': Geben Sie Stunde und Minute im Format HH:MM an.
- 'seconds': Geben Sie Stunde, Minute und Sekunde im Format HH:MM:SS an.
- 'milliseconds': Geben Sie die volle Zeit an, aber kürzen Sie die Sekundenbruchteile auf Millisekunden ab. HH:MM:SS.sss-Format.
- 'microseconds': Geben Sie die Vollzeit im Format HH:MM:SS.ffffff an.
Beispiel für die Verwendung:
void OnStart() { //--- CTime t(14, 30, 55, &tzinfo, 120); // 14:30:55.120 Print(t.isoformat()); // AUTO -> "14:30:55.120" Print(t.isoformat("hours")); // "14" Print(t.isoformat("minutes")); // "14:30" Print(t.isoformat("seconds")); // "14:30:55" Print(t.isoformat("milliseconds")); // "14:30:55.120" }
(d): strftime
Gibt eine Zeichenkette zurück, die die Zeit darstellt, gesteuert durch eine explizite Formatzeichenkette.
string CTime::strftime(string format) { string result = ""; for(int i = 0; i < StringLen(format); i++) { if(StringGetCharacter(format, i) == '%' && i + 1 < StringLen(format)) //Start obtaining the values after a % sign { i++; uchar spec = (uchar)StringGetCharacter(format, i); switch(spec) { case 'H': //Find the H for hour result += StringFormat("%02d", m_hour); break; case 'M': //Put minutes in a place of M result += StringFormat("%02d", m_minute); break; case 'S': //put seconds in a place of S result += StringFormat("%02d", m_second); break; default: result += "%"; result += CharToString(spec); break; } } else result += CharToString((char)StringGetCharacter(format, i)); } return result; }
(e): utcoffset
Wenn tzinfo auf NULL gesetzt ist (Standardeinstellung), gibt diese Funktion INT_MAX zurück; andernfalls gibt sie die Abweichung einer bestimmten Zeitzone von der UTC/GMT-Zeit in Sekunden zurück.
int CTime::tzoffset() { if(m_tzinfo == NULL) return INT_MAX; return m_tzinfo.utcoffset(); }
Beispiel.
void OnStart() { //--- CTZInfo tzinfo("America/New_York"); CTime time(10, 22, 0, &tzinfo); printf("Tzoffset: %d hours",time.tzoffset()/3600); //we divide by 3600 to get the number of hours }
Die Klasse CTZInfo wird im nächsten Abschnitt behandelt.
Ausgabe:
KK 0 12:39:37.184 Time testing (XAUUSD,H1) Tzoffset: -5 hours
Die Zeit der Vereinigten Staaten (New York) ist GMT-5 (5 Stunden hinter UTC).
(f): dst
Gibt INT_MAX zurück, wenn tzinfo auf NULL gesetzt ist (Standardwert); andernfalls wird die Sommerzeit zurückgegeben.
int CTime::dst(void) { if(m_tzinfo == NULL) return INT_MAX; return m_tzinfo.dst(); }
Klasse Zeitzoneninformationen (tzinfo)
In MQL5 haben wir keine integrierte Möglichkeit, auf Informationen aus verschiedenen Zeitzonen zuzugreifen. Dies macht es für unsere Programme zu einer Herausforderung, sich den verschiedenen Zeiten in der Welt bewusst zu sein und relevant zu bleiben.
Python bietet eine integrierte Klasse namens tzinfo, die den Zugriff auf die Zeit aus allen Regionen der Welt ermöglicht.
Gemäß der Dokumentation in Python.
Die Klasse datetime.tzinfo
Dies ist eine abstrakte Basisklasse, was bedeutet, dass diese Klasse nicht direkt instanziiert werden sollte. Definieren Sie eine Unterklasse von tzinfo, um Informationen über eine bestimmte Zeitzone zu erfassen.
Eine Instanz von (einer konkreten Unterklasse von) tzinfo kann an die Konstruktoren für datetime- und time-Objekte übergeben werden. Die letztgenannten Objekte sehen ihre Attribute als in lokaler Zeit, und das tzinfo-Objekt unterstützt Methoden, die den Offset der lokalen Zeit von UTC, den Namen der Zeitzone und den DST-Offset, alle relativ zu einem Datum oder Zeitobjekt, das ihnen übergeben wird, anzeigen.
Sie müssen eine konkrete Unterklasse ableiten und (zumindest) Implementierungen der Standard-Tzinfo-Methoden bereitstellen, die von den von Ihnen verwendeten Datetime-Methoden benötigt werden. Das datetime-Modul bietet time zone, eine einfache konkrete Unterklasse von tzinfo, die Zeitzonen mit festem Offset von UTC wie UTC selbst oder nordamerikanische EST und EDT darstellen kann.
Eine konkrete Unterklasse von tzinfo muss möglicherweise die folgenden Methoden implementieren. Welche Methoden genau benötigt werden, hängt von der Verwendung der bewussten datetime-Objekte ab. Im Zweifelsfall sollten Sie einfach alle umsetzen.
Ähnlich wie die Klasse in der Programmiersprache Python soll die implementierte Klasse CTZInfo in MQL5 harmonisch mit den Klassen CDatetime und CTime zusammenarbeiten und diese beiden Klassen bei der Beschaffung von Informationen über Zeitzonen unterstützen.
Auch wenn Sie die Klasse außerhalb anderer zeitbasierter Klassen aufrufen können, sollten Sie sie nicht für den Zugriff auf ihre Werte, wie die aktuelle Zeit usw., verwenden.
Damit diese Klasse (Modul) funktioniert, brauchen wir eine einheitliche Datenbank mit allen Zeitzoneninformationen. Ich musste alle Informationen aus https://www.iana.org/time-zones extrahieren und in einer Sqlite-Datenbank namens timezonedb.sqlite speichern (am Ende dieses Beitrags angehängt).

Im Klassenkonstruktor wird die obige Datenbank gelesen und eine Verbindung in einer Variablen für die spätere Verwendung innerhalb der Klasse offen gehalten.
#include "sqlite3.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTZInfo { private: CSqlite3 sqlite; string m_zone_name; int utcoffset(datetime utc_time); public: CTZInfo(const string zone_name); ~CTZInfo(void); }; //+------------------------------------------------------------------+ //| Constructor - open timezone database | //+------------------------------------------------------------------+ CTZInfo::CTZInfo(const string zone_name): m_zone_name(zone_name) { string db_name = "timezonedb.sqlite"; if(!sqlite.connect(db_name, true)) { Print("Failed to open timezone DB"); return; } }
Nachfolgend finden Sie einige der in der Klasse bereitgestellten Methoden, die in MQL5 wie in Python implementiert sind, mit leichten Änderungen.
(a): utcoffset
Rückgabe der Abweichung der Ortszeit von UTC in Sekunden. Wenn die Ortszeit westlich von UTC liegt, sollte der zurückgegebene Wert negativ sein; andernfalls ist er positiv.
int CTZInfo::utcoffset() { string query = "SELECT gmt_offset FROM time_zone " "WHERE zone_name='" + m_zone_name + "' AND time_start <= " + (string)(int)TimeGMT() + " " "ORDER BY time_start DESC LIMIT 1;"; vector row = sqlite.execute(query).fetchone(); if(row.Size() == 0) return 0; return (int)row[0]; // seconds offset }
Beispiel.
void OnStart() { //--- CTZInfo tzinfo("America/New_York"); printf("Utc offset: %d hours",tzinfo.utcoffset()/3600); }
Ausgabe:
2025.11.19 17:32:08.699 Time testing (XAUUSD,H1) Utc offset: -5 hours
(b): dst
Rückgabe der Sommerzeitanpassung in Form eines Timedelta-Objekts oder None, wenn keine Sommerzeitinformationen gefunden werden.
int CTZInfo::dst() { string query = "SELECT dst FROM time_zone\n" "WHERE zone_name = '" + m_zone_name + "' " "AND time_start <= " + (string)(int)TimeGMT() + " " "ORDER BY time_start DESC\n" "LIMIT 1;"; //--- vector row = sqlite.execute(query).fetchone(); if(row.Size() == 0) // no result return 0; return (int)row[0]; }
(c): fromutc
Sie nimmt eine UTC-Datumszeit und gibt die lokalisierte Datumszeit zurück (UTC verschoben um den Zeitzonen-Offset für diesen Zeitpunkt).
datetime CTZInfo::fromutc(datetime utc_time) { int offset = utcoffset(utc_time); return (datetime)((int)utc_time + offset); }
Beispiel.
void OnStart() { //--- CTZInfo tzinfo("America/New_York"); Print("From utc: ",tzinfo.fromutc(TimeGMT())); //converts utc time into New york's local time }
Ausgabe:
2025.11.19 17:26:24.400 Time testing (XAUUSD,H1) From utc: 2025.11.19 09:26:24
Die Klasse Timedelta
In Python stellt das Objekt timedelta eine Dauer, die Differenz oder Summe zwischen zwei datetime- oder date-Instanzen dar.
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
Alle Argumente sind optional und stehen standardmäßig auf 0. Die Argumente können ganze Zahlen oder Gleitkommazahlen sein, die positiv oder negativ sein können.
Intern werden nur Tage, Sekunden und Mikrosekunden gespeichert. Argumente werden in diese Einheiten umgerechnet:
- Eine Millisekunde wird in 1000 Mikrosekunden umgerechnet.
- Eine Minute wird in 60 Sekunden umgerechnet.
- Eine Stunde wird in 3600 Sekunden umgerechnet.
- Eine Woche wird in 7 Tage umgerechnet.
und Tage, Sekunden und Mikrosekunden werden dann so normalisiert, dass die Darstellung eindeutig ist, mit
- 0 <= Mikrosekunden < 1000000
- 0 <= Sekunden < 3600*24 (die Anzahl der Sekunden eines Tages)
- -999999999 <= Tage <= 999999999
Nachfolgend finden Sie das MQL5-Äquivalent des Moduls Timedelta aus Python, mit leichten Änderungen.
Keine Millisekunden und Mikrosekunden in den Funktionsargumenten, da diese beiden nicht in der datetime-Variable gespeichert (verfolgt) werden können.
class CTimedelta { public: CTimedelta(void) {}; ~CTimedelta(void) {}; //+------------------------------------------------------------------+ //| | //| For crafting the desired time given the number of days, hours | //| minutes, seconds, and weeks | //| | //+------------------------------------------------------------------+ template <typename T> static T timedelta(uint days = 0, uint hours = 0, uint minutes = 0, uint seconds = 0, uint weeks = 0) { uint delta_seconds = ((days+(weeks*7)) * 86400) + (hours * 3600) + (minutes * 60) + seconds; return delta_seconds; } template <typename T> static T days(uint days_) { return timedelta<T>(days_); } template <typename T> static T hours(uint hours_) { return timedelta<T>(0, hours_); } template <typename T> static T minutes(uint minutes_) { return timedelta<T>(0, 0, minutes_); } template <typename T> static T seconds(uint seconds_) { return timedelta<T>(0, 0, 0, seconds_); } template <typename T> static T weeks(uint weeks_) { return timedelta<T>(0, 0, 0, 0, weeks_); } };
Um diese Klasse wie in Python flexibel zu gestalten, verwenden wir den/die Typenamen, um sicherzustellen, dass wir die Möglichkeit haben, die in Sekunden erstellte Zeit mit Hilfe von Variablen wie (long, int, ulong, double, usw.) und datetime zurückzugeben.
Beispiel für die Verwendung:
#include <PyMQL5\datetime.mqh> //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Print("10 minutes datetime: ",CTimedelta::minutes<datetime>(10)); Print("10 minutes seconds: ",CTimedelta::minutes<int>(10)); datetime now = TimeLocal(); printf("Current time: %s 10 minutes ahead: %s",(string)now, string(now + CTimedelta::minutes<datetime>(10))); printf("Current time: %s 1 week, 2 days, 10 hours, and 5 minutes ahead: %s",string(now), string(now + CTimedelta::timedelta<datetime>(2,10,5,0,1))); }
Ausgabe:
CI 0 17:39:37.748 Time testing (XAUUSD,H1) 10 minutes datetime: 1970.01.01 00:10:00 CL 0 17:39:37.748 Time testing (XAUUSD,H1) 10 minutes seconds: 600 HL 0 17:39:37.748 Time testing (XAUUSD,H1) Current time: 2025.11.20 17:39:37 10 minutes ahead: 2025.11.20 17:49:37 HI 0 17:39:37.748 Time testing (XAUUSD,H1) Current time: 2025.11.20 17:39:37 1 week, 2 days, 10 hours, and 5 minutes ahead: 2025.11.30 03:44:37
Diese einfache Klasse ist wichtig für zeitliche Additions- und Subtraktionsoperationen, die in nativem MQL5 ein wenig schwierig sein können.
Das Objekt der Klasse Datum
Ein Datumsobjekt stellt ein Datum (Jahr, Monat und Tag) dar in einem idealisierten Kalender, dem aktuellen gregorianischen Kalender, der in beide Richtungen unbegrenzt erweitert ist. Betrachten wir diese Klasse als eine nutzerdefinierte Variable (Objekt) „date“.
Von datetime in Python gibt die Funktion „date“ ein Objekt zurück, das alle notwendigen Informationen über das Datum einer bestimmten Zeit enthält.
Beginnend mit einer Möglichkeit, das heutige Datum zurückzugeben.
CDate CDate::today() { m_datetime = TimeLocal(); return CDate(); } Beispiel.
#include <PyMQL5\datetime.mqh> void OnStart() { //--- CDate date; Print("Today's date: ",date.today().__str__()); }
Ausgabe:
2025.11.20 18:14:46.217 Time testing (XAUUSD,H1) Today's date: 2025-11-20
Nachfolgend finden Sie eine Tabelle mit allen notwendigen Funktionen innerhalb der Klasse CDate.
| Funktion | Beschreibung |
|---|---|
CDate::CDate(uint year, uint month, uint day) { if(year < MINYEAR || year > MAXYEAR) Print("ValueError: year out of range"); if(month < 1 || month > 12) Print("ValueError: month out of range"); if(day < 1 || (int)day > DaysInMonth(year, month)) Print("ValueError: day out of range"); m_year = year; m_month = month; m_day = day; } | Ein Konstruktor, dem Jahr, Monat und Tag übergeben wird, um ein nutzerdefiniertes Datum zu erstellen. |
CDate(void); | Standardklassenkonstruktor, der beim Aufruf das heutige Datum in die Klasse setzt. |
CDate::CDate(const datetime time) { MqlDateTime t; TimeToStruct(time, t); m_year = t.year; m_month = t.mon; m_day = t.day; } | Ein nutzerdefinierter Konstruktor, der das Datum aus einer Datetime-Variablen extrahiert, z. B. 18.10.2025 00:00 |
CDate fromtimestamp(datetime ts); | Konvertiert UNIX-Zeitstempel in ein entsprechendes lokales Datum. |
CDate CDate::fromisoformat(string s) | Gibt ein Datum zurück, das einem date_string in einem beliebigen gültigen ISO 8601-Format entspricht. Im Gegensatz zu den Funktionen in den Python datetime-Modulen unterstützt unsere MQL5-Funktion derzeit nur zwei Iso-Formate, die diese Formeln verwenden.
|
CDate fromordinal(int ordinal); | Konvertiert ein ordinales Datum in ein CDate-Objekt. |
const int weekday(); | Gibt den Wochentag als Ganzzahl zurück, wobei Montag 0 und Sonntag 6 ist, ähnlich wie bei MqlDateTime.day. |
const int isoweekday(); | Gibt den Wochentag als Ganzzahl zurück, wobei Montag gleich 1 und Sonntag gleich 7 ist. |
static int DaysInMonth(int year, int month); | Gibt die Anzahl der Tage in einem bestimmten Monat zurück. |
static bool IsLeapYear(int year); | Sie gibt true zurück, wenn ein bestimmtes Jahr ein Schaltjahr ist, andernfalls gibt sie false zurück. |
CDate replace(int year=-1, int month=-1, int day=-1) const | Es ersetzt einen oder mehrere Werte eines gegebenen Datumsobjekts durch einen oder mehrere neue Wert(e). |
Beispiel für die Verwendung:
void OnStart() { //--- CDate date = py_datetime.date(D'29.02.2024'); Print("date: ", date.isoformat()); Print("Weekday: ", date.weekday()); Print("ISO Weekday: ", date.isoweekday()); Print("Ordinal: ", date.toordinal()); Print("Leap year 2024? ", date.IsLeapYear(2024)); Print("__str__: ",date.__str__()); CDate d2 = py_datetime.date().today(); Print("Today: ", d2.isoformat()); Print("From ISO: ", d2.isoformat()); d2 = d2.replace(-1, -1, 30); Print("Replaced: ", d2.isoformat()); //--- from timestamps CDate date3 = date.fromtimestamp(1672531199); Print("Date From timestamps: ",date3.isoformat()); datetime time = py_datetime.fromtimestamp(1672531199); Print("time timestamps: ",time); //--- Print(date_m.fromisoformat("2019-12-04").__str__()); Print(date_m.fromisoformat("20191204").__str__()); //--- CDate today = date.today(); Print(today.ctime()); }
Ausgabe:
OR 0 19:10:29.522 Time testing (XAUUSD,H1) date: 2024-02-29 CD 0 19:10:29.522 Time testing (XAUUSD,H1) Weekday: 3 OQ 0 19:10:29.522 Time testing (XAUUSD,H1) ISO Weekday: 4 CD 0 19:10:29.522 Time testing (XAUUSD,H1) Ordinal: 738945 RD 0 19:10:29.522 Time testing (XAUUSD,H1) Leap year 2024? true HQ 0 19:10:29.522 Time testing (XAUUSD,H1) __str__: 2024-02-29 LJ 0 19:10:29.522 Time testing (XAUUSD,H1) Today: 2025-11-17 LR 0 19:10:29.522 Time testing (XAUUSD,H1) From ISO: 2025-11-17 DD 0 19:10:29.522 Time testing (XAUUSD,H1) Replaced: 2025-11-30 DO 0 19:10:29.522 Time testing (XAUUSD,H1) Date From timestamps: 2023-01-01 EP 0 19:10:29.522 Time testing (XAUUSD,H1) time timestamps: 2023.01.01 02:59:59 QK 0 19:10:29.522 Time testing (XAUUSD,H1) 2019-12-04 OR 0 19:10:29.522 Time testing (XAUUSD,H1) 2019-12-04 CH 0 19:10:29.523 Time testing (XAUUSD,H1) Sun Nov 17 19:10:29 2025
Das datetime-Modul
Das datetime-Modul liefert Klassen zur Bearbeitung von Datums- und Zeitangaben. Diese Klasse (Modul) kombiniert die beiden vorangegangenen Module (Datum und Uhrzeit) mit einigen neu eingeführten Methoden.
Beginnend mit den Klassenkonstruktoren. Einige nehmen die datetime-Variable, andere nehmen Variablen für die Erstellung des Datums und eine bestimmte Uhrzeit dieses Datums.
class CDatetime { protected: CTZInfo *m_tzinfo; MqlDateTime m_datetime_struct; int weekday(const datetime time); public: CDatetime(); CDatetime(const datetime dt, CTZInfo *tzinfo=NULL); CDatetime(uint year, uint month, uint day, uint hour, uint minutes, uint seconds, CTZInfo *tzinfo=NULL); ~CDatetime(void); //--- custom constructor CDatetime datetime_(uint year, uint month, uint day, uint hour, uint minutes, uint seconds, CTZInfo *tzinfo=NULL); CDatetime combine(CDate &date, CTime &time, CTZInfo *tzinfo=NULL)
Die Methode combine kombiniert sowohl Datums- als auch Zeitobjekte, um ein datetime-Objekt zu erstellen.
(a): Die Funktion now
Diese Funktion gibt das aktuelle CDatetime-Objekt in Abhängigkeit von einer bestimmten Zeitzone zurück.
CDatetime CDatetime::now(CTZInfo *tzinfo)
{
return CDatetime(tzinfo.now(), tzinfo);
} Beispiel.
#include <PyMQL5\datetime.mqh> CDatetime py_datetime; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Datetime module testing CTZInfo tzinfo("Africa/Nairobi"); CDatetime now = py_datetime.now(&tzinfo); Print("ctime: ", now.ctime()); }
Ausgabe:
2025.11.21 20:10:03.116 Time testing (XAUUSD,H1) ctime: Fri Nov 21 20:10:03 2025
(b): fromisoformat
Gibt eine Datumszeit zurück, die einem date_string in einem beliebigen gültigen ISO 8601-Format entspricht, mit den folgenden Ausnahmen.
- Zeitzonenverschiebungen können Bruchteile von Sekunden haben.
- Das Trennzeichen T kann durch ein beliebiges Unicode-Zeichen ersetzt werden.
- Bruchteile von Stunden und Minuten werden nicht unterstützt.
- Daten mit reduzierter Genauigkeit werden derzeit nicht unterstützt (JJJJ-MM, JJJJ).
- Erweiterte Datumsdarstellungen werden derzeit nicht unterstützt (±YYYYYY-MM-DD).
- Ordinale Daten werden derzeit nicht unterstützt (JJJJ-OOO).
CDatetime CDatetime::fromisoformat(string iso) { string orig = iso; //--- Split date & time int sep = StringFind(iso, "T"); if(sep == -1) sep = StringFind(iso, " "); if(sep == -1) { Print("Invalid ISO datetime: ", orig); return CDatetime(); } string date_part = StringSubstr(iso, 0, sep); string time_part = StringSubstr(iso, sep + 1); //--- Parse date YYYY-MM-DD string dparts[]; if(StringSplit(date_part, '-', dparts) != 3) { Print("Invalid ISO date: ", orig); return CDatetime(); } int year = (int)StringToInteger(dparts[0]); int mon = (int)StringToInteger(dparts[1]); int day = (int)StringToInteger(dparts[2]); //--- Extract timezone part string tz = ""; int tz_pos = StringFind(time_part, "+"); if(tz_pos == -1) tz_pos = StringFind(time_part, "-"); if(tz_pos == -1) tz_pos = StringFind(time_part, "Z"); if(tz_pos != -1) { tz = StringSubstr(time_part, tz_pos); time_part = StringSubstr(time_part, 0, tz_pos); } //--- Parse time HH:MM:SS(.fff) int hour=0, minute=0, second=0, millisecond=0; string tparts[]; int n = StringSplit(time_part, ':', tparts); if(n < 2) { Print("Invalid ISO time: ", orig); return CDatetime(); } hour = (int)StringToInteger(tparts[0]); minute = (int)StringToInteger(tparts[1]); if(n >= 3) { int dot = StringFind(tparts[2], "."); if(dot != -1) { second = (int)StringToInteger(StringSubstr(tparts[2], 0, dot)); string frac = StringSubstr(tparts[2], dot + 1); millisecond = (int)(StringToInteger(frac) / MathPow(10, StringLen(frac) - 3)); } else { second = (int)StringToInteger(tparts[2]); } } //--- Timezone if provided CTZInfo *tzinfo = NULL; if(tz == "Z") tzinfo = new CTZInfo("UTC"); else if(StringLen(tz) > 0) { string id = "UTC" + tz; // Example: "UTC+03:00" tzinfo = new CTZInfo(id); } return CDatetime(year, mon, day, hour, minute, second, tzinfo); }
Es gibt eine Funktion mit einem ähnlichen Namen in CDate und CTime, aber diese geht noch weiter, da sie sowohl Datum als auch Uhrzeit in einer einzigen formatierten Zeichenkette berücksichtigt.
Beispiel.
CDatetime time = py_datetime.fromisoformat("2011-11-04T00:05:23Z"); Print("datetime: ",time.__str__());
Ausgabe:
2025.11.22 12:47:18.047 Time testing (XAUUSD,H1) datetime: 2011.11.04 00:05:23
(c): isoformat
Konvertiert die im CDatetime-Objekt gespeicherten „datetime“-Informationen in eine als String formatierte Zeit im ISO 8601-Format.
string CDatetime::isoformat(string sep="T", string timespec="auto") { datetime dt = this.__datetime__(); MqlDateTime s; TimeToStruct(dt, s); string hh = StringFormat("%02d", s.hour); string mm = StringFormat("%02d", s.min); string ss = StringFormat("%02d", s.sec); string time_str; if(timespec == "hours") time_str = hh; else if(timespec == "minutes") time_str = hh + ":" + mm; else if(timespec == "seconds") time_str = hh + ":" + mm + ":" + ss; else if(timespec == "milliseconds") time_str = hh + ":" + mm + ":" + ss; else if(timespec == "auto") time_str = hh + ":" + mm + ":" + ss; else time_str = hh + ":" + mm + ":" + ss; string tz = _tz_offset_str(); return StringFormat("%04d-%02d-%02d", s.year, s.mon, s.day) + sep + time_str + tz; }
Beispiel für die Verwendung:
CDatetime time = py_datetime.fromisoformat("2011-11-04T00:05:23Z"); Print("Iso format: ", time.isoformat());
Ausgabe:
2025.11.22 12:47:18.047 Time testing (XAUUSD,H1) Iso format: 2011-11-04T00:05:23
(d): strftime
Formatiert eine in der Klasse gespeicherte Datumsangabe in ein gewünschtes String-Format, in der Regel zu Demonstrationszwecken.
Beispiel.
CDatetime now = py_datetime.now(&tzinfo); string formatted_time = now.strftime("%Y/%M/%d %H:%M:%S"); Print("formatted time: ", formatted_time);
Ausgabe:
2025.11.22 19:55:55.680 Time testing (XAUUSD,H1) formatted time: 2025/55/22 19:55:55
(e): strptime
Diese Methode bewirkt das Gegenteil der Methode strftime, sie kehrt die formatierte Zeit von einem ISO 1806 String-Format in ein Datetime-Objekt um, das in der Klasse CDatetime gespeichert ist.
Beispiel.
CDatetime now = py_datetime.now(&tzinfo); string format = "%Y/%M/%d %H:%M:%S"; string formatted_time = now.strftime(format); Print("formatted time: ", formatted_time); Print("Original time: ", now.strptime(formatted_time, format).__datetime__());
Ausgabe:
OL 0 20:00:47.220 Time testing (XAUUSD,H1) formatted time: 2025/00/22 20:00:47 FF 0 20:00:47.220 Time testing (XAUUSD,H1) Original time: 2025.11.22 20:00:47
Abschließende Überlegungen
Die Neuerstellung von Pythons Modulen für Datum, Uhrzeit und Kalender in MQL5 ist mehr als eine Übung im Umschreiben von Code; sie schließt eine echte Lücke im MQL5-Ökosystem. Durch die Implementierung von Klassen wie CTimedelta, CTime und CDatetime erhalten wir Zugang zu ausdrucksstarken High-Level-Tools zur Zeitmanipulation, die in MetaTrader 5 nicht nativ vorhanden sind.
Diese Ergänzungen ermöglichen zuverlässige Zeitstempelkonvertierungen, den korrekten Umgang mit Zeitzonen und den Aufbau anspruchsvoller Backtesting- oder zeitgesteuerter Systeme.
Das Repository, das den gesamten in dieser Artikelserie besprochenen Code enthält, ist hier zu finden: https://github.com/MegaJoctan/PyMQL5 für Beiträge und Fehlerkorrekturen.
Mit freundlichen Grüßen.
Tabelle der Anhänge
| Dateiname | Beschreibung und Verwendung |
|---|---|
| Include\errordescription.mqh | Enthält Funktionen zur Umwandlung der von MetaTrader 5 und MQL5 erzeugten Fehlercodes in ein für den Menschen lesbares Format. |
| Include\PyMQL5\datetime.mqh | Enthält sowohl die CDate- als auch die CDateTime-Klassen zur Handhabung von Datum und Uhrzeit. |
| Include\PyMQL5\SQLite3.mqh | Ein ähnliches Modul wie sqlite3 in Python, das Funktionen zum Lesen von SQLITE-Datenbanken in MetaTrader 5 bietet. |
| Include\time.mqh | Enthält die Klasse CTime für die Arbeit mit der Zeit. |
| Include\TZInfo.mqh | Sie verfügt über die Klasse CTZInfo zum Lesen der Zeitzoneninformationen aus einer Universalzeitdatenbank. |
| Common\Files\timezonedb.sqlite | Eine SQLite3-Datenbank, die Informationen aus allen Zeitzonen enthält, einschließlich utcoffset, Zeitzonennamen usw. |
| Scripts\Time testing.mq5 | Eine Spielwiese zum Testen aller in diesem Artikel behandelten Methoden und Funktionen. |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19035
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Analytical Volume Profile Trading (AVPT): Liquiditätsarchitektur, Marktgedächtnis und algorithmische Ausführung
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Kagi-Charts in MQL5 beherrschen (Teil I): Erstellen des Indikators
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.