10#include "alkdateformat.h"
12#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
13#include <KCalendarSystem>
18#include <QRegularExpression>
19#include <QRegularExpressionMatch>
22class AlkDateFormat::Private
26 AlkDateFormat::ErrorCode m_errorCode;
31 m_errorCode = errorCode;
33 case AlkDateFormat::NoError:
34 m_errorMessage.
clear();
36 case AlkDateFormat::InvalidFormatString:
37 m_errorMessage =
QString(
"Invalid format string '%1'").
arg(arg1);
39 case AlkDateFormat::InvalidFormatCharacter:
40 m_errorMessage =
QString(
"Invalid format character '%1'").
arg(arg1);
42 case AlkDateFormat::InvalidDate:
43 m_errorMessage =
QString(
"Invalid date '%1'").
arg(arg1);
45 case AlkDateFormat::InvalidDay:
46 m_errorMessage =
QString(
"Invalid day entry: %1").
arg(arg1);
48 case AlkDateFormat::InvalidMonth:
49 m_errorMessage =
QString(
"Invalid month entry: %1").
arg(arg1);
51 case AlkDateFormat::InvalidYear:
52 m_errorMessage =
QString(
"Invalid year entry: %1").
arg(arg1);
54 case AlkDateFormat::InvalidYearLength:
55 m_errorMessage =
QString(
"Length of year (%1) does not match expected length (%2).").
arg(arg1, arg2);
64 if (m_format ==
"UNIX") {
66 const quint64 unixTime = _in.
toUInt(&ok);
72 const QString skroogeFormat = m_format;
76#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
78 if (formatrex.indexIn(m_format) == -1) {
79 return setError(AlkDateFormat::InvalidFormatString, m_format);
82 m_format.
append(formatrex.cap(1));
83 m_format.
append(formatrex.cap(2));
85 m_format.
append(formatrex.cap(3));
86 m_format.
append(formatrex.cap(4));
88 m_format.
append(formatrex.cap(5));
91 auto match = formatrex.match(m_format);
92 if (!
match.hasMatch()) {
93 return setError(AlkDateFormat::InvalidFormatString, m_format);
97 m_format +=
match.captured(1);
98 m_format +=
match.captured(2);
100 m_format +=
match.captured(3);
101 m_format +=
match.captured(4);
103 m_format +=
match.captured(5);
105 date = convertStringKMyMoney(_in,
true, 2000);
106 m_format = skroogeFormat;
109 return setError(AlkDateFormat::InvalidDate, _in);
111 if (!m_format.
contains(QStringLiteral(
"yyyy")) && date.
year() < 2000)
119 quint64 unixTime = _in.
toUInt(&ok);
121 return setError(AlkDateFormat::InvalidDate, _in);
129#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
131 QDate convertStringKMyMoney(
const QString &_in,
bool _strict,
unsigned _centurymidpoint)
134 return convertStringUnix(_in);
142 if (formatrex.indexIn(m_format) == -1) {
143 return setError(AlkDateFormat::InvalidFormatString, m_format);
147 formatParts += formatrex.cap(1);
148 formatParts += formatrex.cap(3);
149 formatParts += formatrex.cap(5);
152 formatDelimiters += formatrex.cap(2);
153 formatDelimiters += formatrex.cap(4);
157 QRegExp specialChars(
"^[\\.\\\\\\?]$");
158 for(it = formatDelimiters.
begin(); it != formatDelimiters.
end(); ++it) {
159 if (specialChars.indexIn(*it) != -1)
174 inputrex.setPattern(
QString(
"(\\w+)\\.?%1(\\w+)\\.?%2(\\w+)\\.?").arg(formatDelimiters[0],
175 formatDelimiters[1]));
177 inputrex.setPattern(
"(\\w+)\\W+(\\w+)\\W+(\\w+)");
180 if (inputrex.indexIn(_in) == -1) {
181 return setError(AlkDateFormat::InvalidDate, _in);
185 scannedParts += inputrex.cap(1).toLower();
186 scannedParts += inputrex.cap(2).toLower();
187 scannedParts += inputrex.cap(3).toLower();
192 unsigned day = 0, month = 0, year = 0;
194 QRegExp digitrex(
"(\\d+)");
197 while (it_scanned != scannedParts.
constEnd()) {
199 switch ((*it_format).at(0).cell()) {
203 if (digitrex.indexIn(*it_scanned) != -1) {
204 day = digitrex.cap(1).toUInt(&ok);
206 if (!ok || day > 31) {
207 return setError(AlkDateFormat::InvalidDay, *it_scanned);
211 month = (*it_scanned).toUInt(&ok);
216 if (KGlobal::locale()->calendar()->monthName(i, 2000).toLower() == *it_scanned
217 || KGlobal::locale()->calendar()->monthName(i, 2000,
218 KCalendarSystem::ShortName).
219 toLower() == *it_scanned) {
226 if (month < 1 || month > 12) {
227 return setError(AlkDateFormat::InvalidMonth, *it_scanned);
232 if (_strict && (*it_scanned).length() != (*it_format).length()) {
233 return setError(AlkDateFormat::InvalidYearLength, *it_scanned, *it_format);
236 year = (*it_scanned).toUInt(&ok);
239 return setError(AlkDateFormat::InvalidYear, *it_scanned);
249 unsigned centuryend = _centurymidpoint + 50;
250 unsigned centurybegin = _centurymidpoint - 50;
252 if (year < centuryend % 100) {
255 year += centurybegin - centurybegin % 100;
264 return setError(AlkDateFormat::InvalidFormatCharacter,
QString((*it_format).at(0).cell()));
270 QDate result(year, month, day);
271 if (!result.isValid()) {
272 return setError(AlkDateFormat::InvalidDate,
QString(
"yr:%1 mo:%2 dy:%3)").arg(year).arg(month).arg(day));
280 QDate convertStringKMyMoney(
const QString& _in,
bool _strict,
unsigned _centurymidpoint)
283 return convertStringUnix(_in);
292 if (!
match.hasMatch()) {
293 return setError(AlkDateFormat::InvalidFormatString, m_format);
297 formatParts +=
match.captured(1);
298 formatParts +=
match.captured(3);
299 formatParts +=
match.captured(5);
302 formatDelimiters +=
match.captured(2);
303 formatDelimiters +=
match.captured(4);
308 for(it = formatDelimiters.
begin(); it != formatDelimiters.
end(); ++it) {
325 inputrex.
setPattern(
QString(
"(\\w+)\\.?%1(\\w+)\\.?%2(\\w+)\\.?").arg(formatDelimiters[0], formatDelimiters[1]));
327 inputrex.
setPattern(
"(\\w+)\\W+(\\w+)\\W+(\\w+)");
330 if (!
match.hasMatch()) {
331 return setError(AlkDateFormat::InvalidDate, _in);
335 scannedParts +=
match.captured(1).toLower();
336 scannedParts +=
match.captured(2).toLower();
337 scannedParts +=
match.captured(3).toLower();
342 unsigned day = 0, month = 0, year = 0;
347 while (it_scanned != scannedParts.
constEnd()) {
349 switch ((*it_format).at(0).cell()) {
353 match = digitrex.match(*it_scanned);
354 if (
match.hasMatch())
355 day =
match.captured(1).toUInt(&ok);
357 return setError(AlkDateFormat::InvalidDay, *it_scanned);
360 month = (*it_scanned).toUInt(&ok);
379 if( !(locale == localeC)) {
382 if (localeC.standaloneMonthName(i).toLower() == *it_scanned
393 if (month < 1 || month > 12)
394 return setError(AlkDateFormat::InvalidMonth, *it_scanned);
398 if (_strict && (*it_scanned).length() != (*it_format).length())
399 return setError(AlkDateFormat::InvalidYearLength, *it_scanned, *it_format);
401 year = (*it_scanned).toUInt(&ok);
404 return setError(AlkDateFormat::InvalidYear, *it_scanned);
413 unsigned centuryend = _centurymidpoint + 50;
414 unsigned centurybegin = _centurymidpoint - 50;
416 if (year < centuryend % 100)
418 year += centurybegin - centurybegin % 100;
426 return setError(AlkDateFormat::InvalidFormatCharacter,
QString(
QChar((*it_format).at(0).cell())));
432 QDate result(year, month, day);
433 if (! result.isValid())
434 return setError(AlkDateFormat::InvalidDate,
QString(
"yr:%1 mo:%2 dy:%3)").arg(year).arg(month).arg(day));
442AlkDateFormat::AlkDateFormat(
const QString &format)
445 d->m_format = format;
452 d->m_format =
right.d->m_format;
456AlkDateFormat::~AlkDateFormat()
463 d->m_format =
right.d->m_format;
468const QString & AlkDateFormat::format()
const
473AlkDateFormat::ErrorCode AlkDateFormat::lastError()
const
475 return d->m_errorCode;
478QString AlkDateFormat::lastErrorMessage()
const
480 return d->m_errorMessage;
483QDate AlkDateFormat::convertString(
const QString& date,
bool strict,
unsigned int centuryMidPoint)
486 d->m_errorCode = NoError;
487 d->m_errorMessage.
clear();
490 return d->convertStringKMyMoney(date, strict, centuryMidPoint);
492 return d->convertStringSkrooge(date);
500 d->m_errorCode = NoError;
501 d->m_errorMessage.
clear();
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
KIOCORE_EXPORT SimpleJob * special(const QUrl &url, const QByteArray &data, JobFlags flags=DefaultFlags)
QDate addYears(int nyears) const const
bool isValid(int year, int month, int day)
QDateTime fromMSecsSinceEpoch(qint64 msecs)
const_iterator constBegin() const const
const_iterator constEnd() const const
QString standaloneMonthName(int month, FormatType type) const const
QRegularExpressionMatch match(QStringView subjectView, qsizetype offset, MatchType matchType, MatchOptions matchOptions) const const
void setPattern(const QString &pattern)
void setPatternOptions(PatternOptions options)
QString & append(QChar ch)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString number(double n, char format, int precision)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toLower() const const
uint toUInt(bool *ok, int base) const const
QTextStream & right(QTextStream &stream)