Ical: add some kind of better parsing when date/time of event is in specified timezone, it sucks before the iCal SPEC is huge and i just cannot implement it all correctly for purpose in rssguard

This commit is contained in:
Martin Rotter 2024-03-13 09:53:36 +01:00
parent 9abb5d1bb5
commit 6479805799
4 changed files with 33 additions and 13 deletions

View file

@ -79,7 +79,7 @@ bool TextFactory::couldBeHtml(const QString& string) {
sstring.startsWith(QL1S("<article")) || sstring.startsWith(QL1S("<details")) || Qt::mightBeRichText(sstring);
}
QDateTime TextFactory::parseDateTime(const QString& date_time) {
QDateTime TextFactory::parseDateTime(const QString& date_time, QString* used_dt_format) {
const QString input_date = date_time.simplified();
if (input_date.isEmpty()) {
@ -104,6 +104,10 @@ QDateTime TextFactory::parseDateTime(const QString& date_time) {
// Make sure that this date/time is considered UTC.
dt.setTimeSpec(Qt::TimeSpec::UTC);
if (used_dt_format != nullptr) {
used_dt_format->append(pattern);
}
// We find offset from UTC.
if (input_date.size() >= TIMEZONE_OFFSET_LIMIT) {
QString offset_sanitized = input_date.mid(pattern.size()).replace(QL1S(" "), QString());

View file

@ -26,7 +26,7 @@ class TextFactory {
// Tries to parse input textual date/time representation.
// Returns invalid date/time if processing fails.
// NOTE: This method tries to always return time in UTC.
static QDateTime parseDateTime(const QString& date_time);
static QDateTime parseDateTime(const QString& date_time, QString* used_dt_format = nullptr);
// Converts 1970-epoch miliseconds to date/time.
// NOTE: This method tries to always return time in UTC.

View file

@ -109,6 +109,16 @@ QString IcalParser::objMessageDescription(const QVariant& msg_element) const {
const IcalendarComponent& comp_base = msg_element.value<IcalendarComponent>();
const EventComponent& comp = static_cast<const EventComponent&>(comp_base);
auto son = comp.startsOn(m_iCalendar.m_tzs);
auto soff = comp.endsOn(m_iCalendar.m_tzs);
QString formaton = son.time().hour() > 0 || son.time().minute() > 0 || son.time().second() > 0
? QLocale().dateTimeFormat(QLocale::FormatType::LongFormat)
: QLocale().dateFormat(QLocale::FormatType::LongFormat);
QString formatoff = soff.time().hour() > 0 || soff.time().minute() > 0 || soff.time().second() > 0
? QLocale().dateTimeFormat(QLocale::FormatType::LongFormat)
: QLocale().dateFormat(QLocale::FormatType::LongFormat);
QString body = QSL("Start date/time: %2<br/>"
"End date/time: %3<br/>"
"Location: %4<br/>"
@ -116,8 +126,8 @@ QString IcalParser::objMessageDescription(const QVariant& msg_element) const {
"<br/>"
"%1")
.arg(comp.description(),
QLocale().toString(comp.startsOn(m_iCalendar.m_tzs)),
QLocale().toString(comp.endsOn(m_iCalendar.m_tzs)),
QLocale().toString(son, formaton),
QLocale().toString(soff, formatoff),
comp.location(),
comp.uid());
@ -297,16 +307,17 @@ QVariant IcalendarComponent::getPropertyValue(const QString& property_name, QStr
}
QDateTime IcalendarComponent::fixupDate(QDateTime dat,
const QString& dt_format,
const QMap<QString, QTimeZone>& time_zones,
const QString& modifiers) const {
// dat.setTimeSpec(Qt::TimeSpec::LocalTime);
// auto xx = dat.toUTC().toString();
bool time_initialized = dt_format.contains('T');
QStringList spl = modifiers.split('=');
if ((dat.time().hour() > 0 || dat.time().minute() > 0 || dat.time().second() > 0) && spl.size() == 2 &&
time_zones.contains(spl.at(1))) {
if (time_initialized && time_zones.contains(spl.at(1))) {
QTimeZone tz = time_zones.value(spl.at(1));
dat.setTimeSpec(Qt::TimeSpec::TimeZone);
@ -326,16 +337,18 @@ QDateTime IcalendarComponent::fixupDate(QDateTime dat,
QDateTime EventComponent::startsOn(const QMap<QString, QTimeZone>& time_zones) const {
QString modifiers;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("DTSTART"), modifiers).toString());
QString dt_format;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("DTSTART"), modifiers).toString(), &dt_format);
return fixupDate(dat, time_zones, modifiers);
return fixupDate(dat, dt_format, time_zones, modifiers);
}
QDateTime EventComponent::endsOn(const QMap<QString, QTimeZone>& time_zones) const {
QString modifiers;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("DTEND"), modifiers).toString());
QString dt_format;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("DTEND"), modifiers).toString(), &dt_format);
return fixupDate(dat, time_zones, modifiers);
return fixupDate(dat, dt_format, time_zones, modifiers);
}
QString EventComponent::title() const {
@ -362,12 +375,12 @@ QDateTime EventComponent::created(const QMap<QString, QTimeZone>& time_zones) co
QString modifiers;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("CREATED"), modifiers).toString());
return fixupDate(dat, time_zones, modifiers);
return fixupDate(dat, {}, time_zones, modifiers);
}
QDateTime EventComponent::lastModified(const QMap<QString, QTimeZone>& time_zones) const {
QString modifiers;
QDateTime dat = TextFactory::parseDateTime(getPropertyValue(QSL("LAST-MODIFIED"), modifiers).toString());
return fixupDate(dat, time_zones, modifiers);
return fixupDate(dat, {}, time_zones, modifiers);
}

View file

@ -18,7 +18,10 @@ class IcalendarComponent {
QVariant getPropertyValue(const QString& property_name) const;
QVariant getPropertyValue(const QString& property_name, QString& property_modifier) const;
QDateTime fixupDate(QDateTime dat, const QMap<QString, QTimeZone>& time_zones, const QString& modifiers) const;
QDateTime fixupDate(QDateTime dat,
const QString& dt_format,
const QMap<QString, QTimeZone>& time_zones,
const QString& modifiers) const;
QVariantMap m_properties;
};