00001
00002
00003
00004
00005
00006
00007 #include "EngaugeAssert.h"
00008 #include "FormatDateTime.h"
00009 #include "Logger.h"
00010 #include <QDateTime>
00011 #include <QTimeZone>
00012
00013
00014 const Qt::TimeSpec REFERENCE_TIME_ZONE (Qt::UTC);
00015
00016 FormatDateTime::FormatDateTime()
00017 {
00018 loadFormatsFormat();
00019 loadFormatsParseAcceptable();
00020 loadFormatsParseIncomplete();
00021 }
00022
00023 bool FormatDateTime::ambiguityBetweenDateAndTime (CoordUnitsDate coordUnitsDate,
00024 CoordUnitsTime coordUnitsTime,
00025 const QString &string) const
00026 {
00027 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::ambiguityBetweenDateAndTime";
00028
00029 bool ambiguous = false;
00030
00031
00032 if (coordUnitsDate != COORD_UNITS_DATE_SKIP &&
00033 coordUnitsTime != COORD_UNITS_TIME_SKIP) {
00034
00035
00036 QStringList fields = string.trimmed().split(QRegExp ("[/- :]"));
00037
00038 if (fields.count() == 1) {
00039
00040
00041
00042 ambiguous = true;
00043 }
00044 }
00045
00046 return ambiguous;
00047 }
00048
00049 void FormatDateTime::dateTimeLookup (const FormatsDate &formatsDateAll,
00050 const FormatsTime &formatsTimeAll,
00051 CoordUnitsDate coordUnitsDate,
00052 CoordUnitsTime coordUnitsTime,
00053 const QString &string,
00054 bool useQDateTimeElseQRegExp,
00055 double &value,
00056 bool &success) const
00057 {
00058 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::dateTimeLookup";
00059
00060 success = false;
00061
00062 ENGAUGE_ASSERT (formatsDateAll.contains (coordUnitsDate));
00063 ENGAUGE_ASSERT (formatsTimeAll.contains (coordUnitsTime));
00064
00065 QStringList formatsDate = formatsDateAll [coordUnitsDate];
00066 QStringList formatsTime = formatsTimeAll [coordUnitsTime];
00067
00068
00069 QStringList::const_iterator itrDate, itrTime;
00070 bool iterating = true;
00071 for (itrDate = formatsDate.begin(); itrDate != formatsDate.end() && iterating; itrDate++) {
00072
00073 QString formatDate = *itrDate;
00074
00075 for (itrTime = formatsTime.begin(); itrTime != formatsTime.end() && iterating; itrTime++) {
00076
00077 QString formatTime = *itrTime;
00078
00079
00080 QString separator = (!formatDate.isEmpty() && !formatTime.isEmpty() ? " " : "");
00081
00082 QString formatDateTime = formatDate + separator + formatTime;
00083
00084 if (!formatDateTime.isEmpty()) {
00085
00086
00087 if (useQDateTimeElseQRegExp) {
00088
00089 QDateTime dt = QDateTime::fromString (string,
00090 formatDateTime);
00091
00092 if (dt.isValid() && !ambiguityBetweenDateAndTime (coordUnitsDate,
00093 coordUnitsTime,
00094 string)) {
00095
00096 success = true;
00097 value = dt.toTimeSpec (REFERENCE_TIME_ZONE).toTime_t ();
00098 iterating = false;
00099
00100 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::dateTimeLookup"
00101 << " string=" << string.toLatin1().data()
00102 << " qDateTimeFormatMatched=" << formatDateTime.toLatin1().data()
00103 << " value=" << value
00104 << " stringQDateTime=" << dt.toString().toLatin1().data();
00105
00106 }
00107 } else {
00108
00109 QRegExp reg (formatDateTime);
00110 if (reg.exactMatch(string)) {
00111
00112 success = true;
00113 iterating = false;
00114
00115 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::dateTimeLookup"
00116 << " string=" << string.toLatin1().data()
00117 << " regExpMatched=" << formatDateTime.toLatin1().data();
00118
00119 }
00120 }
00121 }
00122 }
00123 }
00124 }
00125
00126 QString FormatDateTime::formatOutput (CoordUnitsDate coordUnitsDate,
00127 CoordUnitsTime coordUnitsTime,
00128 double value) const
00129 {
00130 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::formatOutput"
00131 << " value=" << value;
00132
00133 ENGAUGE_ASSERT (m_formatsDateFormat.contains (coordUnitsDate));
00134 ENGAUGE_ASSERT (m_formatsTimeFormat.contains (coordUnitsTime));
00135
00136 QString format = m_formatsDateFormat [coordUnitsDate] + " " + m_formatsTimeFormat [coordUnitsTime];
00137 format = format.trimmed();
00138
00139 QDateTime dt = QDateTime::fromTime_t (value);
00140
00141 return dt.toTimeSpec(REFERENCE_TIME_ZONE).toString (format);
00142 }
00143
00144 void FormatDateTime::loadFormatsFormat()
00145 {
00146 m_formatsDateFormat [COORD_UNITS_DATE_SKIP] = "";
00147 m_formatsDateFormat [COORD_UNITS_DATE_MONTH_DAY_YEAR] = "MM/dd/yyyy";
00148 m_formatsDateFormat [COORD_UNITS_DATE_DAY_MONTH_YEAR] = "dd/MM/yyyy";
00149 m_formatsDateFormat [COORD_UNITS_DATE_YEAR_MONTH_DAY] = "yyyy/MM/dd";
00150
00151 ENGAUGE_ASSERT (m_formatsDateFormat.count () == NUM_COORD_UNITS_DATE);
00152
00153 m_formatsTimeFormat [COORD_UNITS_TIME_SKIP] = "";
00154 m_formatsTimeFormat [COORD_UNITS_TIME_HOUR_MINUTE] = "hh/mm";
00155 m_formatsTimeFormat [COORD_UNITS_TIME_HOUR_MINUTE_SECOND] = "hh:mm:ss";
00156
00157 ENGAUGE_ASSERT (m_formatsTimeFormat.count () == NUM_COORD_UNITS_TIME);
00158 }
00159
00160 void FormatDateTime::loadFormatsParseAcceptable()
00161 {
00162 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::loadFormatsParseAcceptable";
00163
00164 QStringList skip, dayMonth, dayMonthYear, monthDay, monthDayYear, yearMonth, yearMonthDay;
00165
00166
00167
00168 skip << "";
00169
00170 dayMonth << "d/M"
00171 << "d-M"
00172 << "d/MM"
00173 << "d-MM"
00174 << "d/MMM"
00175 << "d-MMM"
00176 << "d/MMMM"
00177 << "d-MMMM"
00178 << "dd/M"
00179 << "dd-M"
00180 << "dd/M"
00181 << "dd-M"
00182 << "dd/MM"
00183 << "dd-MM"
00184 << "dd/MMM"
00185 << "dd-MMM"
00186 << "dd/MMMM"
00187 << "dd-MMMM";
00188 dayMonthYear << "d/M/yyyy"
00189 << "d-M-yyyy"
00190
00191 << "d/MM/yyyy"
00192 << "d-MM-yyyy"
00193 << "d/MMM/yyyy"
00194 << "d-MMM-yyyy"
00195 << "d MMM yyyy"
00196 << "d/MMMM/yyyy"
00197 << "d-MMMM-yyyy"
00198 << "d MMMM yyyy"
00199
00200 << "dd/MM/yyyy"
00201 << "dd-MM-yyyy"
00202 << "dd/MMM/yyyy"
00203 << "dd-MMM-yyyy"
00204 << "dd MMM yyyy"
00205 << "dd/MMMM/yyyy"
00206 << "dd-MMMM-yyyy"
00207 << "dd MMMM yyyy";
00208 monthDay << "M/d"
00209 << "M-d"
00210 << "M d"
00211 << "M/dd"
00212 << "M-dd"
00213 << "M dd"
00214 << "MM/d"
00215 << "MM-d"
00216 << "MM d"
00217 << "MM/dd"
00218 << "MM-dd"
00219 << "MM dd"
00220 << "MMM/d"
00221 << "MMM-d"
00222 << "MMM d"
00223 << "MMM/dd"
00224 << "MMM-dd"
00225 << "MMM dd"
00226 << "MMMM/d"
00227 << "MMMM-d"
00228 << "MMMM d"
00229 << "MMMM/dd"
00230 << "MMMM-dd"
00231 << "MMMM dd";
00232 monthDayYear << "M/d/yyyy"
00233 << "M-d-yyyy"
00234 << "M d yyyy"
00235 << "M/dd/yyyy"
00236 << "M-dd-yyyy"
00237 << "M dd yyyy"
00238 << "MM/d/yyyy"
00239 << "MM-d-yyyy"
00240 << "MM d yyyy"
00241 << "MM/dd/yyyy"
00242 << "MM-dd-yyyy"
00243 << "MM dd yyyy"
00244 << "MMM/d/yyyy"
00245 << "MMM-d-yyyy"
00246 << "MMM d yyyy"
00247 << "MMM/dd/yyyy"
00248 << "MMM-dd-yyyy"
00249 << "MMM dd yyyy"
00250 << "MMMM/d/yyyy"
00251 << "MMMM-d-yyyy"
00252 << "MMMM d"
00253 << "MMMM/dd"
00254 << "MMMM-dd"
00255 << "MMMM dd";
00256 yearMonth << "yyyy/M"
00257 << "yyyy-M"
00258 << "yyyy M"
00259 << "yyyy/MM"
00260 << "yyyy-MM"
00261 << "yyyy MM"
00262 << "yyyy/MMM"
00263 << "yyyy-MMM"
00264 << "yyyy MMM"
00265 << "yyyy/MMMM"
00266 << "yyyy-MMMM"
00267 << "yyyy MMMM";
00268 yearMonthDay << "yyyy/M/d"
00269 << "yyyy-M-d"
00270 << "yyyy M d"
00271 << "yyyy/M/dd"
00272 << "yyyy-M-dd"
00273 << "yyyy M dd"
00274 << "yyyy/MM/dd"
00275 << "yyyy-MM-dd"
00276 << "yyyy MM dd"
00277 << "yyyy/MMM/d"
00278 << "yyyy-MMM-d"
00279 << "yyyy MMM d"
00280 << "yyyy/MMM/dd"
00281 << "yyyy-MMM-dd"
00282 << "yyyy MMM dd"
00283 << "yyyy/MMMM/dd"
00284 << "yyyy-MMMM-dd"
00285 << "yyyy MMMM dd";
00286
00287
00288 m_formatsDateParseAcceptable [COORD_UNITS_DATE_SKIP] = skip + monthDay + monthDayYear + yearMonthDay;
00289 m_formatsDateParseAcceptable [COORD_UNITS_DATE_MONTH_DAY_YEAR] = skip + monthDay + monthDayYear + yearMonthDay;
00290 m_formatsDateParseAcceptable [COORD_UNITS_DATE_DAY_MONTH_YEAR] = skip + dayMonth + dayMonthYear + yearMonthDay;
00291 m_formatsDateParseAcceptable [COORD_UNITS_DATE_YEAR_MONTH_DAY] = skip + yearMonth + yearMonthDay;
00292
00293 ENGAUGE_ASSERT (m_formatsDateParseAcceptable.count () == NUM_COORD_UNITS_DATE);
00294
00295 QStringList hour, hourMinute, hourMinuteSecond, hourMinutePm, hourMinuteSecondPm;
00296
00297 hour << "hh";
00298 hourMinute << "hh:mm";
00299 hourMinuteSecond << "hh:mm:ss";
00300 hourMinutePm << "hh:mmA"
00301 << "hh:mm A"
00302 << "hh:mma"
00303 << "hh:mm a";
00304 hourMinuteSecondPm << "hh:mm:ssA"
00305 << "hh:mm:ss A"
00306 << "hh:mm:ssa"
00307 << "hh:mm:ss a";
00308
00309 m_formatsTimeParseAcceptable [COORD_UNITS_TIME_SKIP] = skip + hour + hourMinute + hourMinuteSecond + hourMinutePm + hourMinuteSecondPm;
00310 m_formatsTimeParseAcceptable [COORD_UNITS_TIME_HOUR_MINUTE] = skip + hour + hourMinute + hourMinutePm + hourMinuteSecond + hourMinuteSecondPm;
00311 m_formatsTimeParseAcceptable [COORD_UNITS_TIME_HOUR_MINUTE_SECOND] = skip + hour + hourMinute + hourMinutePm + hourMinuteSecond + hourMinuteSecondPm;
00312
00313 ENGAUGE_ASSERT (m_formatsTimeParseAcceptable.count () == NUM_COORD_UNITS_TIME);
00314 }
00315
00316 void FormatDateTime::loadFormatsParseIncomplete()
00317 {
00318 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::loadFormatsParseIncomplete";
00319
00320 QStringList skip, day, dayMonth, month, monthDay, monthDayYear, year, yearMonth, yearMonthDay;
00321
00322
00323
00324 skip << "";
00325
00326
00327
00328 day << "\\d{1,2}"
00329 << "\\d{1,2}/"
00330 << "\\d{1,2}-";
00331 dayMonth << "\\d{1,2}/\\d{1,2}"
00332 << "\\d{1,2}/\\d{1,2} "
00333 << "\\d{1,2}/\\d{1,2}/"
00334 << "\\d{1,2}-\\d{1,2}-"
00335 << "\\d{1,2}/[a-zA-Z]{1,12}/"
00336 << "\\d{1,2}-[a-zA-Z]{1,12}-"
00337 << "\\d{1,2} [a-zA-Z]{1,12} ";
00338 month << "\\d{1,2}"
00339 << "\\d{1,2}/"
00340 << "[a-zA-Z]{1,12}"
00341 << "[a-zA-Z]{1,12} ";
00342 monthDay << "\\d{1,2}/\\d{1,2}"
00343 << "\\d{1,2}/\\d{1,2} "
00344 << "\\d{1,2}/\\d{1,2}/"
00345 << "\\d{1,2} \\d{1,2}"
00346 << "\\d{1,2} \\d{1,2} "
00347 << "\\d{1,2}-\\d{1,2}-"
00348 << "[a-zA-Z]{1,12}"
00349 << "[a-zA-Z]{1,12} "
00350 << "[a-zA-Z]{1,12} \\d{1,2}"
00351 << "[a-zA-Z]{1,12} \\d{1,2} ";
00352 monthDayYear << "\\d{1,2}/\\d{1,2}/\\d{1,4}"
00353 << "\\d{1,2}/\\d{1,2}/\\d{1,4} "
00354 << "\\d{1,2}-\\d{1,2}-\\d{1,4}"
00355 << "\\d{1,2}-\\d{1,2}-\\d{1,4} "
00356 << "\\d{1,2} \\d{1,2} \\d{1,4}"
00357 << "\\d{1,2} \\d{1,2} \\d{1,4} ";
00358 year << "\\d{1,4}"
00359 << "\\d{1,4} "
00360 << "\\d{1,4}/"
00361 << "\\d{1,4}-";
00362 yearMonth << "\\d{4}/\\d{1,2}"
00363 << "\\d{4}/\\d{1,2} "
00364 << "\\d{4}/\\d{1,2}/"
00365 << "\\d{4}-\\d{1,2}"
00366 << "\\d{4}-\\d{1,2} "
00367 << "\\d{4}-\\d{1,2}-"
00368 << "\\d{4} \\d{1,2}"
00369 << "\\d{4} \\d{1,2} "
00370 << "\\d{4}/[a-zA-Z]{1,12}"
00371 << "\\d{4}/[a-zA-Z]{1,12} "
00372 << "\\d{4}/[a-zA-Z]{1,12}/"
00373 << "\\d{4}-[a-zA-Z]{1,12}"
00374 << "\\d{4}-[a-zA-Z]{1,12} "
00375 << "\\d{4}-[a-zA-Z]{1,12}-"
00376 << "\\d{4} [a-zA-Z]{1,12}"
00377 << "\\d{4} [a-zA-Z]{1,12} ";
00378 yearMonthDay << "\\d{4}/\\d{1,2}/\\d{1,2}"
00379 << "\\d{4}/\\d{1,2}-\\d{1,2}"
00380 << "\\d{4} \\d{1,2} \\d{1,2}"
00381 << "\\d{4}/[a-zA-Z]{1,12}/\\d{1,2}"
00382 << "\\d{4}-[a-zA-Z]{1,12}-\\d{1,2}";
00383
00384
00385
00386 m_formatsDateParseIncomplete [COORD_UNITS_DATE_SKIP] = skip + month + monthDay + monthDayYear + year + yearMonth + yearMonthDay;
00387 m_formatsDateParseIncomplete [COORD_UNITS_DATE_MONTH_DAY_YEAR] = skip + month + monthDay + monthDayYear + year + yearMonth + yearMonthDay;
00388 m_formatsDateParseIncomplete [COORD_UNITS_DATE_DAY_MONTH_YEAR] = skip + day + dayMonth + year + yearMonth + yearMonthDay;
00389 m_formatsDateParseIncomplete [COORD_UNITS_DATE_YEAR_MONTH_DAY] = skip + year + yearMonth + yearMonthDay;
00390
00391 ENGAUGE_ASSERT (m_formatsDateParseIncomplete.count () == NUM_COORD_UNITS_DATE);
00392
00393 QStringList hour, hourMinute, hourMinuteAmPm, hourMinuteSecond, hourMinuteSecondAmPm;
00394
00395 hour << "\\d{1,2}"
00396 << "\\d{1,2}:";
00397 hourMinute << "\\d{1,2}:\\d{1,2}"
00398 << "\\d{1,2}:\\d{1,2}:"
00399 << "\\d{1,2}:\\d{1,2} ";
00400 hourMinuteAmPm << "\\d{1,2}:\\d{1,2} [aApP]";
00401 hourMinuteSecond << "\\d{1,2}:\\d{1,2}:\\d{1,2}"
00402 << "\\d{1,2}:\\d{1,2}:\\d{1,2} ";
00403 hourMinuteSecondAmPm << "\\d{1,2}:\\d{1,2}:\\d{1,2} [aApP]";
00404
00405
00406 m_formatsTimeParseIncomplete [COORD_UNITS_TIME_SKIP] = skip +
00407 hour +
00408 hourMinute + hourMinuteAmPm +
00409 hourMinuteSecond + hourMinuteSecondAmPm;
00410 m_formatsTimeParseIncomplete [COORD_UNITS_TIME_HOUR_MINUTE] = skip +
00411 hour +
00412 hourMinute + hourMinuteAmPm +
00413 hourMinuteSecond + hourMinuteSecondAmPm;
00414 m_formatsTimeParseIncomplete [COORD_UNITS_TIME_HOUR_MINUTE_SECOND] = skip +
00415 hour +
00416 hourMinute + hourMinuteAmPm +
00417 hourMinuteSecond + hourMinuteSecondAmPm;
00418
00419 ENGAUGE_ASSERT (m_formatsTimeParseIncomplete.count () == NUM_COORD_UNITS_TIME);
00420 }
00421
00422 QValidator::State FormatDateTime::parseInput (CoordUnitsDate coordUnitsDate,
00423 CoordUnitsTime coordUnitsTime,
00424 const QString &stringUntrimmed,
00425 double &value) const
00426 {
00427 LOG4CPP_INFO_S ((*mainCat)) << "FormatDateTime::parseInput"
00428 << " date=" << coordUnitsDateToString (coordUnitsDate).toLatin1().data()
00429 << " time=" << coordUnitsTimeToString (coordUnitsTime).toLatin1().data()
00430 << " string=" << stringUntrimmed.toLatin1().data();
00431
00432 const bool USE_QREGEXP = true, DO_NOT_USE_QREGEXP = false;
00433
00434 const QString string = stringUntrimmed.trimmed();
00435
00436 QValidator::State state;
00437 if (string.isEmpty()) {
00438
00439 state = QValidator::Intermediate;
00440
00441 } else {
00442
00443 state = QValidator::Invalid;
00444
00445
00446 bool success = false;
00447 dateTimeLookup (m_formatsDateParseAcceptable,
00448 m_formatsTimeParseAcceptable,
00449 coordUnitsDate,
00450 coordUnitsTime,
00451 string,
00452 USE_QREGEXP,
00453 value,
00454 success);
00455 if (success) {
00456
00457 state = QValidator::Acceptable;
00458
00459 } else {
00460
00461
00462 dateTimeLookup (m_formatsDateParseIncomplete,
00463 m_formatsTimeParseIncomplete,
00464 coordUnitsDate,
00465 coordUnitsTime,
00466 string,
00467 DO_NOT_USE_QREGEXP,
00468 value,
00469 success);
00470 if (success) {
00471
00472 state = QValidator::Intermediate;
00473
00474 }
00475 }
00476 }
00477
00478 return state;
00479 }