373 lines
7.8 KiB
C++
Executable File
373 lines
7.8 KiB
C++
Executable File
#include "ngltools_dtg.h"
|
|
|
|
#include <QString>
|
|
#include <QDateTime>
|
|
|
|
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")
|
|
};
|
|
}
|
|
|
|
}
|