#include "ngltools_dtg.h" #include #include namespace DTG { static char s_timezone = 'Z'; static char s_userDefinedTimezone = s_timezone; static char s_exerciseDefaultTimezone = s_timezone; int timezone2Hours(char tz, bool *bOk) { if (!isTimezoneValid(tz)) { if (bOk) *bOk = false; return 0; } if (bOk) *bOk = true; if (tz < 'J') return tz - 'A' + 1; if (tz < 'N') return tz - 'A'; if (tz < 'Z') return 'Z' - tz - 13; return 0; } int timezone2Secs(char tz, bool *bOk) { return 3600 * timezone2Hours(tz, bOk) ; } bool setTimezone(char tz, bool bUserDefinedZone) { if (!isTimezoneValid(tz)) { if (!(tz == 0 && bUserDefinedZone)) return false; } if (bUserDefinedZone) s_userDefinedTimezone = tz; else s_exerciseDefaultTimezone = tz; s_timezone = s_userDefinedTimezone != 0 ? s_userDefinedTimezone : s_exerciseDefaultTimezone; return true; } char timezone() { return s_timezone; } char timezoneUserDefined() { return s_userDefinedTimezone; } char timezoneExerciseDefault() { return s_exerciseDefaultTimezone; } bool isTimezoneValid(char tz) { tz = toupper(tz); return !(tz < 'A' || tz == 'J' || tz > 'Z'); } static DateTimeType s_dateTimeType = DDMMYYYY_Z_HHMMSS; static DisplayFormat s_defaultDisplayFormat = Long; void setDateTimeType(DateTimeType dtType) { s_dateTimeType = dtType; } DateTimeType dateTimeType() { return s_dateTimeType; } void setDefaultDisplayFormat(DisplayFormat dtFormat) { s_defaultDisplayFormat = dtFormat; } DisplayFormat defaultDisplayFormat() { return s_defaultDisplayFormat; } QString toString(const QDateTime &dt, DisplayFormat format, DateTimeType type) { if (format == Default) format = s_defaultDisplayFormat; static const QDateTime dtNull = QDateTime::fromSecsSinceEpoch(0); if (!dt.isValid() || dt == dtNull) return QString(); const QDateTime dateTime = dt.toUTC().addSecs(timezone2Hours(s_timezone) * 3600); QString ret; switch (type) { case DTG: { QString str1; if (format == Long) str1 = dateTime.toString(QLatin1String("dd hhmmss")); else if (format == TurboLong) str1 = dateTime.toString(QLatin1String("dd hhmmss.z")); else { ret = dateTime.toString(QLatin1String("ddhhmm")) + QLatin1Char(s_timezone); break; } const int month = dateTime.date().month() - 1; const int year = dateTime.date().year() - 2000; ret = QStringLiteral("%1 %2 %3 %4") .arg(str1) .arg(QLatin1Char(s_timezone)) .arg(months().at(month)) .arg(year, 2, 10, QLatin1Char('0')); } break; case DDMMYYYY_HHMMSS_Z: { if (format == Long) ret = dateTime.toString(QLatin1String("dd.MM.yyyy HH:mm:ss")) + QLatin1Char(s_timezone); else ret = dateTime.toString(QLatin1String("dd.MM HH:mm")) + QLatin1Char(s_timezone); } break; case DDMMYYYY_Z_HHMMSS: if (format == Long) ret = dateTime.toString(QLatin1String("dd.MM.yyyy ")) + QLatin1Char(s_timezone) + dateTime.toString(QLatin1String(" HH:mm:ss")); else ret = dateTime.toString(QLatin1String("dd.MM ")) + QLatin1Char(s_timezone) + dateTime.toString(QLatin1String(" HH:mm")); break; } return ret; } QString toStringMSec(qint64 msecSinceEpoch, DisplayFormat format) { if (msecSinceEpoch <= 0) return QString(); return toString(QDateTime::fromMSecsSinceEpoch(msecSinceEpoch), format); } static bool check24(const QChar *input, int *output) { const int i1 = input[0].unicode() - '0'; const int i2 = input[1].unicode() - '0'; if (i1 > 2) return false; if (i1 == 2 && i2 > 5) return false; if (output) *output = i1 * 10 + i2; return true; } static bool check31(const QChar *input, int *output = nullptr) { const int i1 = input[0].unicode() - '0'; const int i2 = input[1].unicode() - '0'; if (i1 > 3) return false; if (i1 == 3 && i2 > 1) return false; if (output) *output = i1 * 10 + i2; return true; } static bool check60(const QChar *input, int *output) { const int i1 = input[0].unicode() - '0'; const int i2 = input[1].unicode() - '0'; if (i1 > 5) return false; if (output) *output = i1 * 10 + i2; return true; } static DTGValidation validate18(const QString &input, QDateTime &dt) { int hh, mm, ss; for (int i = 0; i < 2; ++i) { if (!input[i].isDigit()) return Invalid; } if (!check31(&input.data() [0])) return Invalid; if (input[2] != QLatin1Char(' ')) return Invalid; if (input.length() == 7) { for (int i = 3; i < 7; ++i) { if (!input[i].isDigit()) return Invalid; } return Intermediate; } for (int i = 3; i < 9; ++i) { if (!input[i].isDigit()) return Invalid; } if (!check24(&input.data() [3], &hh)) return Invalid; if (!check60(&input.data() [5], &mm)) return Invalid; if (!check60(&input.data() [7], &ss)) return Invalid; if (input[9] != QLatin1Char(' ')) return Invalid; const QChar c = input[10]; if (c < QLatin1Char('A') || c > QLatin1Char('Z')) return Invalid; if (c == QLatin1Char('J')) { return Invalid; } const QString mon = input.mid(12, 3); int month = months().indexOf(mon); if (month < 0) { return Invalid; } for (int i = 16; i < 18; ++i) { if (!input[i].isDigit()) return Invalid; } const int day = input.leftRef(2).toInt(); const int year = input.midRef(16, 2).toInt() + 2000; dt = QDateTime(QDate(year, month + 1, day), QTime(hh, mm, ss), Qt::UTC); if (!dt.isValid()) { return Invalid; } dt = dt.addSecs(-timezone2Hours(c.toLatin1()) * 3600); return Acceptable; } static DTGValidation validate7(const QString &input, QDateTime &dt) { int hh, mm; for (int i = 0; i < 6; ++i) { if (!input[i].isDigit()) return Invalid; } if (!check31(&input.data() [0])) return Invalid; if (!check24(&input.data() [2], &hh)) return Invalid; if (!check60(&input.data() [4], &mm)) return Invalid; const QChar c = input[6]; if (c < QLatin1Char('A') || c > QLatin1Char('Z')) return Invalid; if (c == QLatin1Char('J')) { return Invalid; } const int day = input.leftRef(2).toInt(); const QDate curDate = QDate::currentDate(); dt = QDateTime(QDate(curDate.year(), curDate.month(), day), QTime(hh, mm), Qt::UTC); if (!dt.isValid()) { return Invalid; } dt = dt.addSecs(-timezone2Hours(c.toLatin1()) * 3600); return Acceptable; } QDateTime fromDTGString(const QString &str, bool *bOk) { if (bOk) *bOk = false; QDateTime dt; if (str.length() == 7) { DTGValidation state = validate7(str, dt); if (state == Acceptable && bOk) *bOk = true; } else if (str.length() == 18) { DTGValidation state = validate18(str, dt); if (state == Acceptable && bOk) *bOk = true; } return dt; } DTGValidation validateString(const QString &str, QDateTime &dt) { const int len = str.length(); if (len == 7 || len == 18) { if (len == 18 || (str[2] == QLatin1Char(' '))) return validate18(str, dt); return validate7(str, dt); } return Invalid; } QStringList months() { return { QLatin1String("jan"), QLatin1String("feb"), QLatin1String("mar"), QLatin1String("apr"), QLatin1String("may"), QLatin1String("jun"), QLatin1String("jul"), QLatin1String("aug"), QLatin1String("sep"), QLatin1String("oct"), QLatin1String("nov"), QLatin1String("dec") }; } }