File indexing completed on 2024-04-14 14:20:04

0001 /*
0002     Copyright 2010 John Layt <john@layt.net>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Library General Public
0006     License as published by the Free Software Foundation; either
0007     version 2 of the License, or (at your option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     Library General Public License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to
0016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017     Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "klocalizeddate.h"
0021 
0022 #include "kcalendarsystem.h"
0023 
0024 #include <QDebug>
0025 #include <QDataStream>
0026 
0027 /*****************************************************************************
0028  *
0029  *                               Private Section
0030  *
0031  *****************************************************************************/
0032 
0033 class KLocalizedDatePrivate : public QSharedData
0034 {
0035 public:
0036     KDELIBS4SUPPORT_DEPRECATED explicit KLocalizedDatePrivate(const QDate &date, const KCalendarSystem *calendar, bool manageCalendar);
0037     KLocalizedDatePrivate(const KLocalizedDatePrivate &rhs);
0038     KLocalizedDatePrivate &operator=(const KLocalizedDatePrivate &rhs);
0039     virtual ~KLocalizedDatePrivate();
0040 
0041     QDate m_date;
0042     const KCalendarSystem *m_calendar;
0043     bool m_manageCalendar;
0044 };
0045 
0046 KLocalizedDatePrivate::KLocalizedDatePrivate(const QDate &date, const KCalendarSystem *calendar, bool manageCalendar)
0047     : QSharedData(),
0048       m_date(date),
0049       m_calendar(calendar),
0050       m_manageCalendar(manageCalendar)
0051 {
0052 }
0053 
0054 KLocalizedDatePrivate::KLocalizedDatePrivate(const KLocalizedDatePrivate &rhs)
0055     : QSharedData(rhs),
0056       m_date(rhs.m_date),
0057       m_calendar(rhs.m_calendar),
0058       m_manageCalendar(rhs.m_manageCalendar)
0059 {
0060     // If we're managing the calendar object, then take a copy,
0061     // i.e. user called setCalendarSystem() rather than passing a custom one into the constructor
0062     if (m_manageCalendar) {
0063         m_calendar =  KCalendarSystem::create(m_calendar->calendarSystem(), new KLocale(*m_calendar->locale()));
0064     }
0065 }
0066 
0067 KLocalizedDatePrivate &KLocalizedDatePrivate::operator=(const KLocalizedDatePrivate &rhs)
0068 {
0069     m_date = rhs.m_date;
0070     m_calendar = rhs.m_calendar;
0071     m_manageCalendar = rhs.m_manageCalendar;
0072     // If we're managing the calendar object, then take a copy,
0073     // i.e. user called setCalendarSystem() rather than passing a custom one into the constructor
0074     if (rhs.m_manageCalendar) {
0075         m_calendar =  KCalendarSystem::create(m_calendar->calendarSystem(), new KLocale(*m_calendar->locale()));
0076     }
0077     return *this;
0078 }
0079 
0080 KLocalizedDatePrivate::~KLocalizedDatePrivate()
0081 {
0082     // If we're managing the calendar object, then delete it,
0083     // i.e. user called setCalendarSystem() rather than passing a custom one into the constructor
0084     if (m_manageCalendar) {
0085         delete m_calendar;
0086     }
0087 }
0088 
0089 /*****************************************************************************
0090  *
0091  *                            Date Creation Section
0092  *
0093  *****************************************************************************/
0094 
0095 KLocalizedDate::KLocalizedDate(const QDate &date, const KCalendarSystem *calendarSystem)
0096     : d(new KLocalizedDatePrivate(date, calendarSystem, false))
0097 {
0098 }
0099 
0100 KLocalizedDate::KLocalizedDate(int year, int month, int day, const KCalendarSystem *calendarSystem)
0101     : d(new KLocalizedDatePrivate(QDate(), calendarSystem, false))
0102 {
0103     setDate(year, month, day);
0104 }
0105 
0106 KLocalizedDate::KLocalizedDate(const KLocalizedDate &rhs)
0107     : d(new KLocalizedDatePrivate(*rhs.d))
0108 {
0109 }
0110 
0111 KLocalizedDate &KLocalizedDate::operator=(const KLocalizedDate &rhs)
0112 {
0113     *d = *rhs.d;
0114     return *this;
0115 }
0116 
0117 KLocalizedDate &KLocalizedDate::operator=(const QDate &rhs)
0118 {
0119     d->m_date = rhs;
0120     return *this;
0121 }
0122 
0123 KLocalizedDate::~KLocalizedDate()
0124 {
0125 }
0126 
0127 /*****************************************************************************
0128  *
0129  *                           Calendar System Section
0130  *
0131  *****************************************************************************/
0132 
0133 void KLocalizedDate::setCalendarSystem(KLocale::CalendarSystem calendarSystem)
0134 {
0135     if (calendarSystem == calendar()->calendarSystem()) {
0136         return;
0137     }
0138     KCalendarSystem *newCalendar =  KCalendarSystem::create(calendarSystem,
0139                                     new KLocale(*calendar()->locale()));
0140     if (d->m_manageCalendar) {
0141         delete d->m_calendar;
0142     }
0143     d->m_calendar = newCalendar;
0144 }
0145 
0146 KLocale::CalendarSystem KLocalizedDate::calendarSystem()
0147 {
0148     return calendar()->calendarSystem();
0149 }
0150 
0151 const KCalendarSystem *KLocalizedDate::calendar() const
0152 {
0153     if (d->m_calendar) {
0154         return d->m_calendar;
0155     }
0156     return  KLocale::global()->calendar();
0157 }
0158 
0159 /*****************************************************************************
0160  *
0161  *                           Date Status Section
0162  *
0163  *****************************************************************************/
0164 
0165 bool KLocalizedDate::isNull() const
0166 {
0167     return date().isNull();
0168 }
0169 
0170 bool KLocalizedDate::isValid() const
0171 {
0172     return calendar()->isValid(date());
0173 }
0174 
0175 /*****************************************************************************
0176  *
0177  *                           Date Setting Section
0178  *
0179  *****************************************************************************/
0180 
0181 bool KLocalizedDate::setDate(const QDate &date)
0182 {
0183     d->m_date = date;
0184     return isValid();
0185 }
0186 
0187 bool KLocalizedDate::setDate(int year, int month, int day)
0188 {
0189     calendar()->setDate(d->m_date, year, month, day);
0190     return isValid();
0191 }
0192 
0193 bool KLocalizedDate::setDate(int year, int dayOfYear)
0194 {
0195     calendar()->setDate(d->m_date, year, dayOfYear);
0196     return isValid();
0197 }
0198 
0199 bool KLocalizedDate::setDate(QString eraName, int yearInEra, int month, int day)
0200 {
0201     calendar()->setDate(d->m_date, eraName, yearInEra, month, day);
0202     return isValid();
0203 }
0204 
0205 bool KLocalizedDate::setDate(KLocale::WeekNumberSystem weekNumberSystem, int year, int isoWeekNumber, int dayOfIsoWeek)
0206 {
0207     Q_UNUSED(weekNumberSystem); // Only support ISO Week at the moment
0208     calendar()->setDateIsoWeek(d->m_date, year, isoWeekNumber, dayOfIsoWeek);
0209     return isValid();
0210 }
0211 
0212 bool KLocalizedDate::setCurrentDate()
0213 {
0214     d->m_date = QDate::currentDate();
0215     return isValid();
0216 }
0217 
0218 /*****************************************************************************
0219  *
0220  *                        Static Date Creation Section
0221  *
0222  *****************************************************************************/
0223 
0224 KLocalizedDate KLocalizedDate::currentDate()
0225 {
0226     return KLocalizedDate(QDate::currentDate());
0227 }
0228 
0229 KLocalizedDate KLocalizedDate::fromDate(const QDate &date)
0230 {
0231     return KLocalizedDate(date);
0232 }
0233 
0234 KLocalizedDate KLocalizedDate::fromJulianDay(int jd)
0235 {
0236     return KLocalizedDate(QDate::fromJulianDay(jd));
0237 }
0238 
0239 /*****************************************************************************
0240  *
0241  *                             Date Componant Section
0242  *
0243  *****************************************************************************/
0244 
0245 int KLocalizedDate::toJulianDay() const
0246 {
0247     return d->m_date.toJulianDay();
0248 }
0249 
0250 QDate KLocalizedDate::date() const
0251 {
0252     return d->m_date;
0253 }
0254 
0255 void KLocalizedDate::getDate(int *year, int *month, int *day) const
0256 {
0257     calendar()->getDate(date(), year, month, day);
0258 }
0259 
0260 int KLocalizedDate::year() const
0261 {
0262     return calendar()->year(date());
0263 }
0264 
0265 int KLocalizedDate::month() const
0266 {
0267     return calendar()->month(date());
0268 }
0269 
0270 int KLocalizedDate::day() const
0271 {
0272     return calendar()->day(date());
0273 }
0274 
0275 QString KLocalizedDate::eraName() const
0276 {
0277     return formatDate(KLocale::EraName);
0278 }
0279 
0280 QString KLocalizedDate::eraYear() const
0281 {
0282     return formatDate(KLocale::EraYear);
0283 }
0284 
0285 int KLocalizedDate::yearInEra() const
0286 {
0287     return calendar()->yearInEra(date());
0288 }
0289 
0290 int KLocalizedDate::dayOfYear() const
0291 {
0292     return calendar()->dayOfYear(date());
0293 }
0294 
0295 int KLocalizedDate::dayOfWeek() const
0296 {
0297     return calendar()->dayOfWeek(date());
0298 }
0299 
0300 int KLocalizedDate::week(int *yearNum) const
0301 {
0302     return calendar()->week(date(), yearNum);
0303 }
0304 
0305 int KLocalizedDate::week(KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const
0306 {
0307     return calendar()->week(date(), weekNumberSystem, yearNum);
0308 }
0309 
0310 int KLocalizedDate::monthsInYear() const
0311 {
0312     return calendar()->monthsInYear(date());
0313 }
0314 
0315 int KLocalizedDate::weeksInYear() const
0316 {
0317     return calendar()->weeksInYear(date());
0318 }
0319 
0320 int KLocalizedDate::weeksInYear(KLocale::WeekNumberSystem weekNumberSystem) const
0321 {
0322     return calendar()->weeksInYear(date(), weekNumberSystem);
0323 }
0324 
0325 int KLocalizedDate::daysInYear() const
0326 {
0327     return calendar()->daysInYear(date());
0328 }
0329 
0330 int KLocalizedDate::daysInMonth() const
0331 {
0332     return calendar()->daysInMonth(date());
0333 }
0334 
0335 int KLocalizedDate::daysInWeek() const
0336 {
0337     return calendar()->daysInWeek(date());
0338 }
0339 
0340 bool KLocalizedDate::isLeapYear() const
0341 {
0342     return calendar()->isLeapYear(date());
0343 }
0344 
0345 /*****************************************************************************
0346  *
0347  *                             Date Formatting Section
0348  *
0349  *****************************************************************************/
0350 
0351 QString KLocalizedDate::formatDate(KLocale::DateFormat toFormat) const
0352 {
0353     return calendar()->formatDate(date(), toFormat);
0354 }
0355 
0356 QString KLocalizedDate::formatDate(const QString &toFormat, KLocale::DateTimeFormatStandard formatStandard) const
0357 {
0358     return calendar()->formatDate(date(), toFormat, formatStandard);
0359 }
0360 
0361 QString KLocalizedDate::formatDate(KLocale::DateTimeComponent component,
0362                                    KLocale::DateTimeComponentFormat format,
0363                                    KLocale::WeekNumberSystem weekNumberSystem) const
0364 {
0365     return calendar()->formatDate(date(), component, format, weekNumberSystem);
0366 }
0367 
0368 /*****************************************************************************
0369  *
0370  *                             Date Parsing Section
0371  *
0372  *****************************************************************************/
0373 
0374 KLocalizedDate KLocalizedDate::readDate(const QString &dateString,
0375                                         KLocale::DateTimeParseMode parseMode,
0376                                         const KCalendarSystem *calendar)
0377 {
0378     Q_UNUSED(parseMode);
0379     if (!calendar) {
0380         calendar = KLocale::global()->calendar();
0381     }
0382     return KLocalizedDate(calendar->readDate(dateString));
0383 }
0384 
0385 KLocalizedDate KLocalizedDate::readDate(const QString &dateString,
0386                                         KLocale::ReadDateFlags formatFlags,
0387                                         KLocale::DateTimeParseMode parseMode,
0388                                         const KCalendarSystem *calendar)
0389 {
0390     Q_UNUSED(parseMode);
0391     if (!calendar) {
0392         calendar = KLocale::global()->calendar();
0393     }
0394     return KLocalizedDate(calendar->readDate(dateString, formatFlags));
0395 }
0396 
0397 KLocalizedDate KLocalizedDate::readDate(const QString &dateString,
0398                                         const QString &dateFormat,
0399                                         KLocale::DateTimeParseMode parseMode,
0400                                         KLocale::DateTimeFormatStandard formatStandard,
0401                                         const KCalendarSystem *calendar)
0402 {
0403     Q_UNUSED(parseMode);
0404     if (!calendar) {
0405         calendar = KLocale::global()->calendar();
0406     }
0407     return KLocalizedDate(calendar->readDate(dateString, dateFormat, nullptr, formatStandard));
0408 }
0409 
0410 /*****************************************************************************
0411  *
0412  *                             Date Maths Section
0413  *
0414  *****************************************************************************/
0415 
0416 KLocalizedDate KLocalizedDate::addYears(int years) const
0417 {
0418     KLocalizedDate newDate;
0419     newDate = *this;
0420     newDate.setDate(calendar()->addYears(date(), years));
0421     return newDate;
0422 }
0423 
0424 bool KLocalizedDate::addYearsTo(int years)
0425 {
0426     d->m_date = calendar()->addYears(date(), years);
0427     return isValid();
0428 }
0429 
0430 KLocalizedDate KLocalizedDate::addMonths(int months) const
0431 {
0432     KLocalizedDate newDate(*this);
0433     newDate.setDate(calendar()->addMonths(date(), months));
0434     return newDate;
0435 }
0436 
0437 bool KLocalizedDate::addMonthsTo(int months)
0438 {
0439     d->m_date = calendar()->addMonths(date(), months);
0440     return isValid();
0441 }
0442 
0443 KLocalizedDate KLocalizedDate::addDays(int days) const
0444 {
0445     KLocalizedDate newDate(*this);
0446     newDate.setDate(calendar()->addDays(date(), days));
0447     return newDate;
0448 }
0449 
0450 bool KLocalizedDate::addDaysTo(int days)
0451 {
0452     d->m_date = calendar()->addDays(date(), days);
0453     return isValid();
0454 }
0455 
0456 void KLocalizedDate::dateDifference(const KLocalizedDate &toDate,
0457                                     int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const
0458 {
0459     dateDifference(toDate.date(), yearsDiff, monthsDiff, daysDiff, direction);
0460 }
0461 
0462 void KLocalizedDate::dateDifference(const QDate &toDate,
0463                                     int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const
0464 {
0465     calendar()->dateDifference(date(), toDate, yearsDiff, monthsDiff, daysDiff, direction);
0466 }
0467 
0468 int KLocalizedDate::yearsDifference(const KLocalizedDate &toDate) const
0469 {
0470     return yearsDifference(toDate.date());
0471 }
0472 
0473 int KLocalizedDate::yearsDifference(const QDate &toDate) const
0474 {
0475     return calendar()->yearsDifference(date(), toDate);
0476 }
0477 
0478 int KLocalizedDate::monthsDifference(const KLocalizedDate &toDate) const
0479 {
0480     return monthsDifference(toDate.date());
0481 }
0482 
0483 int KLocalizedDate::monthsDifference(const QDate &toDate) const
0484 {
0485     return calendar()->monthsDifference(date(), toDate);
0486 }
0487 
0488 int KLocalizedDate::daysDifference(const KLocalizedDate &toDate) const
0489 {
0490     return daysDifference(toDate.date());
0491 }
0492 
0493 int KLocalizedDate::daysDifference(const QDate &toDate) const
0494 {
0495     return calendar()->daysDifference(date(), toDate);
0496 }
0497 
0498 KLocalizedDate KLocalizedDate::firstDayOfYear() const
0499 {
0500     KLocalizedDate newDate(*this);
0501     newDate.setDate(calendar()->firstDayOfYear(date()));
0502     return newDate;
0503 }
0504 
0505 KLocalizedDate KLocalizedDate::lastDayOfYear() const
0506 {
0507     KLocalizedDate newDate(*this);
0508     newDate.setDate(calendar()->lastDayOfYear(date()));
0509     return newDate;
0510 }
0511 
0512 KLocalizedDate KLocalizedDate::firstDayOfMonth() const
0513 {
0514     KLocalizedDate newDate(*this);
0515     newDate.setDate(calendar()->firstDayOfMonth(date()));
0516     return newDate;
0517 }
0518 
0519 KLocalizedDate KLocalizedDate::lastDayOfMonth() const
0520 {
0521     KLocalizedDate newDate(*this);
0522     newDate.setDate(calendar()->lastDayOfMonth(date()));
0523     return newDate;
0524 }
0525 
0526 /*****************************************************************************
0527  *
0528  *                             Date Operators Section
0529  *
0530  *****************************************************************************/
0531 
0532 bool KLocalizedDate::operator==(const KLocalizedDate &rhs) const
0533 {
0534     return (date() == rhs.date());
0535 }
0536 
0537 bool KLocalizedDate::operator==(const QDate &rhs) const
0538 {
0539     return (date() == rhs);
0540 }
0541 
0542 bool KLocalizedDate::operator!=(const KLocalizedDate &rhs) const
0543 {
0544     return (date() != rhs.date());
0545 }
0546 
0547 bool KLocalizedDate::operator!=(const QDate &rhs) const
0548 {
0549     return (date() != rhs);
0550 }
0551 
0552 bool KLocalizedDate::operator<(const KLocalizedDate &rhs) const
0553 {
0554     return (date() < rhs.date());
0555 }
0556 
0557 bool KLocalizedDate::operator<(const QDate &rhs) const
0558 {
0559     return (date() < rhs);
0560 }
0561 
0562 bool KLocalizedDate::operator<=(const KLocalizedDate &rhs) const
0563 {
0564     return (d->m_date <= rhs.date());
0565 }
0566 
0567 bool KLocalizedDate::operator<=(const QDate &rhs) const
0568 {
0569     return (date() <= rhs);
0570 }
0571 
0572 bool KLocalizedDate::operator>(const KLocalizedDate &rhs) const
0573 {
0574     return (date() > rhs.date());
0575 }
0576 
0577 bool KLocalizedDate::operator>(const QDate &rhs) const
0578 {
0579     return (date() > rhs);
0580 }
0581 
0582 bool KLocalizedDate::operator>=(const KLocalizedDate &rhs) const
0583 {
0584     return (date() >= rhs.date());
0585 }
0586 
0587 bool KLocalizedDate::operator>=(const QDate &rhs) const
0588 {
0589     return (date() >= rhs);
0590 }
0591 
0592 QDataStream &operator<<(QDataStream &out, const KLocalizedDate &date)
0593 {
0594     return out << (quint32)(date.toJulianDay()) << date.calendar()->calendarSystem();
0595 }
0596 
0597 QDataStream &operator>>(QDataStream &in, KLocalizedDate &date)
0598 {
0599     quint32 jd;
0600     int calendarSystem;
0601     in >> jd >> calendarSystem;
0602     date.setDate(QDate::fromJulianDay(jd));
0603     date.setCalendarSystem((KLocale::CalendarSystem)calendarSystem);
0604     return in;
0605 }
0606 
0607 QDebug operator<<(QDebug dbg, const KLocalizedDate &date)
0608 {
0609     if (date.calendar()->calendarSystem() == KLocale::QDateCalendar) {
0610         dbg.nospace() << "KLocalizedDate(" << date.formatDate(KLocale::IsoDate) << ", "
0611                       << date.calendar()->calendarLabel() << ')';
0612     } else {
0613         dbg.nospace() << "KLocalizedDate(" << date.formatDate(KLocale::IsoDate) << ", "
0614                       << date.calendar()->calendarLabel() << ')'
0615                       << " = QDate(" << date.date().toString(Qt::ISODate) << ')';
0616     }
0617     return dbg.space();
0618 }