33 #include "holidayparserdriverplan_p.h"
34 #include "holidayscannerplan_p.h"
35 #include "holidayparserplan.hpp"
43 #include "holiday_p.h"
50 using namespace KHolidays;
54 m_traceParsing( false ),
55 m_traceScanning( false ),
56 m_parseMetadataOnly( false )
58 QFile holidayFile( filePath() );
59 if ( holidayFile.open( QIODevice::ReadOnly ) ) {
60 m_scanData = holidayFile.readAll();
64 m_scanner->set_debug( m_traceScanning );
67 m_fileToParse =
new std::string( filePath().toLocal8Bit().data() );
81 Q_UNUSED( errorLocation );
84 kDebug() << errorMessage;
89 kDebug() << errorMessage;
96 foreach (
const QString &calendar, m_fileCalendarTypes ) {
104 for ( m_parseYear = m_parseStartYear; m_parseYear <= m_parseEndYear; ++m_parseYear ) {
106 m_parseCalendar->setDate( m_parseYearStart, m_parseYear, 1, 1 );
107 m_parseYearEaster = easter( m_parseYear );
108 m_parseYearPascha = pascha( m_parseYear );
110 std::istringstream iss2( std::string( m_scanData.data() ) );
111 m_scanner->yyrestart( &iss2 );
121 m_parseMetadataOnly =
true;
122 m_fileCountryCode.clear();
123 m_fileLanguageCode.clear();
125 m_fileDescription.clear();
126 m_fileCalendarTypes.clear();
127 m_fileCalendarTypes.append( QLatin1String(
"gregorian") );
131 m_parseYear = QDate::currentDate().year();
132 std::istringstream iss2( std::string( m_scanData.data() ) );
133 m_scanner->yyrestart( &iss2 );
135 m_resultList.clear();
140 QFileInfo file( m_filePath );
141 if ( file.exists() ) {
142 QStringList metadata = file.fileName().split( QLatin1Char(
'_') );
143 if ( metadata[0] == QLatin1String(
"holiday") && metadata.count() > 2 ) {
144 if ( m_fileCountryCode.isEmpty() ) {
145 setFileCountryCode( metadata[1].toUpper() );
147 if ( m_fileLanguageCode.isEmpty() ) {
148 QStringList language = metadata[2].split( QLatin1Char(
'-') );
149 m_fileLanguageCode = language[0];
150 if ( language.count() > 1 ) {
151 setFileLanguageCode( language[0].append( QLatin1Char(
'_') ).append( language[1].toUpper() ) );
153 setFileLanguageCode( language[0] );
156 if ( m_fileLanguageCode.isEmpty() && metadata.count() > 3 ) {
157 m_fileName = metadata[3];
162 m_parseMetadataOnly =
false;
165 QString HolidayParserDriverPlan::filePath()
170 std::string *HolidayParserDriverPlan::fileToParse()
const
172 return m_fileToParse;
180 int HolidayParserDriverPlan::adjustedMonthNumber(
int month )
182 if ( m_eventCalendarType != QLatin1String(
"hebrew") ||
183 m_parseCalendar->calendarType() != QLatin1String(
"hebrew") ||
184 !m_parseCalendar->isLeapYear( m_parseYear ) ||
200 bool HolidayParserDriverPlan::isLeapYear(
int year )
202 return m_parseCalendar->isLeapYear( year );
205 int HolidayParserDriverPlan::parseYear()
210 int HolidayParserDriverPlan::monthsInYear(
int year )
213 m_parseCalendar->setDate( tempDate, year, 1, 1 );
214 return m_parseCalendar->monthsInYear( tempDate );
217 int HolidayParserDriverPlan::daysInMonth(
int year,
int month )
220 m_parseCalendar->setDate( tempDate, year, month, 1 );
221 return m_parseCalendar->daysInMonth( tempDate );
224 int HolidayParserDriverPlan::julianDay(
int year,
int month,
int day )
227 m_parseCalendar->setDate( tempDate, year, month, day );
228 return tempDate.toJulianDay();
231 void HolidayParserDriverPlan::julianDayToDate(
int jd,
int *year,
int *month,
int *day )
233 QDate tempDate = QDate::fromJulianDay( jd );
236 *year = m_parseCalendar->year( tempDate );
239 *month = m_parseCalendar->month( tempDate );
242 *day = m_parseCalendar->day( tempDate );
246 QDate HolidayParserDriverPlan::easter(
int year )
248 if ( m_parseCalendar->calendarType() != QLatin1String(
"gregorian") ) {
256 int h = ( c - ( c / 4 ) - ( ( ( 8 * c ) + 13 ) / 25 ) + ( 19 * g ) + 15 ) % 30;
257 int i = h - ( ( h / 28 ) * ( 1 - ( ( 29 / ( h + 1 ) ) * ( ( 21 - g ) / 11 ) ) ) );
258 int j = ( year + ( year / 4 ) + i + 2 - c + ( c / 4 ) ) % 7;
260 int month = 3 + ( ( l + 40 ) / 44 );
261 int day = l + 28 - ( 31 * ( month / 4 ) );
263 return QDate::fromJulianDay( julianDay( year, month, day ) );
267 QDate HolidayParserDriverPlan::pascha(
int year )
269 if ( m_parseCalendar->calendarType() == QLatin1String(
"gregorian") ||
270 m_parseCalendar->calendarType() == QLatin1String(
"julian") ) {
275 int i = ( ( 19 * g ) + 15 ) % 30;
276 int j = ( year + ( year / 4 ) + i ) % 7;
278 int month = 3 + ( ( l + 40 ) / 44 );
279 int day = l + 28 - ( 31 * ( month / 4 ) );
281 if ( m_parseCalendar->calendarType() == QLatin1String(
"julian") ) {
282 return QDate::fromJulianDay( julianDay( year, month, day ) );
285 if ( m_parseCalendar->calendarType() == QLatin1String(
"gregorian") ) {
287 int paschaJd = julianDay( year, month, day );
289 return QDate::fromJulianDay( paschaJd );
302 int HolidayParserDriverPlan::julianDayFromEventName(
const QString &eventName )
304 foreach (
const KHolidays::Holiday &thisHoliday, m_resultList ) {
305 if ( thisHoliday.text() == eventName ) {
306 return thisHoliday.date().toJulianDay();
313 int HolidayParserDriverPlan::julianDayFromEaster(
void )
315 if ( m_eventCalendarType == QLatin1String(
"gregorian") ) {
316 return m_parseYearEaster.toJulianDay();
318 error( QLatin1String(
"Can only use Easter in Gregorian event rule") );
324 int HolidayParserDriverPlan::julianDayFromPascha(
void )
326 if ( m_eventCalendarType == QLatin1String(
"gregorian") || m_eventCalendarType == QLatin1String(
"julian") ) {
327 return m_parseYearPascha.toJulianDay();
329 error( QLatin1String(
"Can only use Easter in Gregorian or Julian event rule") );
335 int HolidayParserDriverPlan::julianDayFromMonthDay(
int month,
int day ) {
336 return julianDay( m_parseYear, month, day );
340 int HolidayParserDriverPlan::julianDayFromRelativeWeekday(
int occurrence,
int weekday,
int jd )
342 if ( occurrence == ANY ) {
346 int thisWeekday = m_parseCalendar->dayOfWeek( QDate::fromJulianDay( jd ) );
350 if ( occurrence > 0 ) {
351 occurrence = occurrence - 1;
352 }
else if ( occurrence < 0 && weekday == thisWeekday ) {
353 occurrence = occurrence + 1;
356 if ( weekday < thisWeekday ) {
357 occurrence = occurrence + 1;
360 return jd + weekday - thisWeekday + ( occurrence * 7 );
364 int HolidayParserDriverPlan::julianDayFromWeekdayInMonth(
int occurrence,
int weekday,
int month )
366 if ( occurrence == LAST ) {
367 return julianDayFromRelativeWeekday( BEFORE, weekday, julianDay( m_parseYear, month, daysInMonth( m_parseYear, month ) ) );
369 return julianDayFromRelativeWeekday( occurrence, weekday, julianDay( m_parseYear, month, 1 ) );
378 void HolidayParserDriverPlan::setFileCountryCode(
const QString &countryCode )
380 m_fileCountryCode = countryCode;
383 void HolidayParserDriverPlan::setFileLanguageCode(
const QString &languageCode )
385 m_fileLanguageCode = languageCode;
388 void HolidayParserDriverPlan::setFileName(
const QString &name )
393 void HolidayParserDriverPlan::setFileDescription(
const QString &description )
395 m_fileDescription = description;
398 void HolidayParserDriverPlan::setEventName(
const QString &eventName )
400 m_eventName = eventName;
403 void HolidayParserDriverPlan::setEventColorName(
int nameColor )
405 m_eventColorName = nameColor;
408 void HolidayParserDriverPlan::setEventColorDay(
int dayColor )
410 m_eventColorDay = dayColor;
413 void HolidayParserDriverPlan::setEventCalendarType(
const QString &calendarType )
415 m_eventCalendarType = calendarType;
416 if ( m_parseMetadataOnly && !m_fileCalendarTypes.contains( calendarType ) ) {
417 m_fileCalendarTypes.append( calendarType );
421 void HolidayParserDriverPlan::setEventDate(
int eventYear,
int eventMonth,
int eventDay )
423 m_eventYear = eventYear;
424 m_eventMonth = eventMonth;
425 m_eventDay = eventDay;
428 void HolidayParserDriverPlan::setEventDate(
int jd )
430 julianDayToDate( jd, &m_eventYear, &m_eventMonth, &m_eventDay );
443 void HolidayParserDriverPlan::setFromWeekdayInMonth(
int occurrence,
int weekday,
int month,
int offset,
int duration )
446 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
450 int startMonth, endMonth;
451 if ( month == LAST ) {
452 startMonth = monthsInYear( m_parseYear );
453 endMonth = startMonth;
454 }
else if ( month == ANY ) {
456 endMonth = monthsInYear( m_parseYear );
463 for (
int thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) {
465 if ( m_parseCalendar->isValid( m_parseYear, thisMonth, 1 ) ) {
466 int startOccurrence, endOccurrence;
467 if ( occurrence == ANY ) {
471 startOccurrence = occurrence;
472 endOccurrence = occurrence;
475 int jdMonthStart = julianDay( m_parseYear, thisMonth, 1 );
476 int jdMonthEnd = julianDay( m_parseYear, thisMonth, daysInMonth( m_parseYear, thisMonth ) );
479 for (
int thisOccurrence = startOccurrence; thisOccurrence <= endOccurrence; ++thisOccurrence ) {
480 int thisJd = julianDayFromWeekdayInMonth( thisOccurrence, weekday, thisMonth );
481 if ( thisJd >= jdMonthStart && thisJd <= jdMonthEnd ) {
482 setEvent( thisJd + offset, 0, duration );
496 void HolidayParserDriverPlan::setFromRelativeWeekday(
int occurrence,
int weekday,
int offset,
int duration )
499 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
504 if ( m_eventYear == ANY ) {
505 thisYear = m_parseYear;
507 thisYear = m_eventYear;
510 int startMonth, endMonth;
511 if ( m_eventMonth == LAST ) {
512 startMonth = monthsInYear( thisYear );
513 endMonth = startMonth;
514 }
else if ( m_eventMonth == ANY ) {
516 endMonth = monthsInYear( thisYear );
518 startMonth = m_eventMonth;
519 endMonth = m_eventMonth;
524 for ( thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) {
526 int startDay, endDay;
527 if ( m_eventDay == LAST ) {
528 startDay = daysInMonth( thisYear, thisMonth );
530 }
else if ( m_eventDay == ANY ) {
532 endDay = daysInMonth( thisYear, thisMonth );
534 startDay = m_eventDay;
539 for (
int thisDay = startDay; thisDay <= endDay; ++thisDay ) {
540 if ( m_parseCalendar->isValid( thisYear, thisMonth, thisDay ) ) {
541 int relativeJd = julianDayFromRelativeWeekday( occurrence, weekday, julianDay( thisYear, thisMonth, thisDay ) );
542 setEvent( relativeJd + offset, 0, duration );
550 int HolidayParserDriverPlan::conditionalOffset(
int year,
int month,
int day,
int condition )
560 m_parseCalendar->setDate( tempDate, year, month, day );
561 int weekday = m_parseCalendar->dayOfWeek( tempDate );
563 if ( condition & ( 1 << weekday ) ) {
565 int to = ( condition >> 8 );
566 while ( !( to & ( 1 << ( ( weekday + offset ) % 7 ) ) ) && ( offset < 8 ) ) {
584 void HolidayParserDriverPlan::setFromDate(
int offset,
int condition,
int duration )
587 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
592 if ( m_eventYear == ANY ) {
593 thisYear = m_parseYear;
595 thisYear = m_eventYear;
598 int startMonth, endMonth;
599 if ( m_eventMonth == LAST ) {
600 startMonth = monthsInYear( thisYear );
601 endMonth = startMonth;
602 }
else if ( m_eventMonth == ANY ) {
604 endMonth = monthsInYear( thisYear );
606 startMonth = m_eventMonth;
607 endMonth = m_eventMonth;
611 for (
int thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) {
613 int startDay, endDay;
614 if ( m_eventDay == LAST ) {
615 startDay = daysInMonth( thisYear, thisMonth );
617 }
else if ( m_eventDay == ANY ) {
619 endDay = daysInMonth( thisYear, thisMonth );
621 startDay = m_eventDay;
626 for (
int thisDay = startDay; thisDay <= endDay; ++thisDay ) {
628 if ( m_parseCalendar->isValid( thisYear, thisMonth, thisDay ) ) {
629 setEvent( julianDay( thisYear, thisMonth, thisDay ) + offset,
630 conditionalOffset( thisYear, thisMonth, thisDay, condition ), duration );
644 void HolidayParserDriverPlan::setFromEaster(
int offset,
int duration )
647 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
651 if ( m_eventCalendarType == QLatin1String(
"gregorian") ) {
652 setEvent( m_parseYearEaster.toJulianDay() + offset, 0, duration );
654 error( QLatin1String(
"Can only use Easter in Gregorian event rule") );
664 void HolidayParserDriverPlan::setFromPascha(
int offset,
int duration )
667 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
671 if ( m_eventCalendarType == QLatin1String(
"gregorian") || m_eventCalendarType == QLatin1String(
"julian") ) {
672 setEvent( m_parseYearPascha.toJulianDay(), offset, duration );
674 error( QLatin1String(
"Can only use Pascha in Julian and Gregorian event rule") );
679 void HolidayParserDriverPlan::setEvent(
int jd,
int observeOffset,
int duration )
682 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) {
687 int observeJd = jd + observeOffset;
689 if ( m_multidayMode == Holiday::MultidayHolidaysAsSingleEvents ) {
690 addHoliday( QDate::fromJulianDay( observeJd ), duration );
693 for (
int dd = 0; dd < duration; ++dd ) {
694 addHoliday( QDate::fromJulianDay( observeJd + dd ), 1 );
699 void HolidayParserDriverPlan::addHoliday(
const QDate &observedDate,
int duration )
702 if ( m_parseCalendar->isValid( observedDate ) &&
703 observedDate <= m_requestEnd &&
704 observedDate.addDays( duration - 1 ) >= m_requestStart ) {
705 KHolidays::Holiday holiday;
706 holiday.d->mObservedDate = observedDate;
707 holiday.d->mDuration = duration;
708 holiday.d->mText = m_eventName;
709 holiday.d->mShortText = m_eventName;
710 if ( m_eventColorName == 2 || m_eventColorName == 9 ||
711 m_eventColorDay == 2 || m_eventColorDay == 9 ) {
712 holiday.d->mDayType = KHolidays::Holiday::NonWorkday;
714 holiday.d->mDayType = KHolidays::Holiday::Workday;
716 m_resultList.append( holiday );
virtual void setParseStartEnd()
Initialise parse year variables for calendar system.
void error(const KHolidays::location &errorLocation, const QString &errorMessage)
Bison C++ skeleton error message handling.
~HolidayParserDriverPlan()
Destructor.
HolidayParserDriver abstract base class.
HolidayScannerPlan implementation class.
void set_debug_level(debug_level_type l)
Set the current debugging level.
void parseMetadata()
Parse the file for metadata only and populate the metadata variables.
virtual int parse()
Parse.
virtual void setParseCalendar(const QString &calendarType)
Set the calendar system to use.
void parse()
Actually parse the file, new plan format implementation.
HolidayParserDriverPlan(const QString &planFilename)
Constructor of Plan file parser driver.