Permalink
Browse files

Remove XMLTV TimeOffset setting and improve xmltv date parsing

The XMLTV spec requires that the grabber do one of two things:
1) Supply dates and times in GMT
2) Include a timezone/time offset in ISO8601 format with datetime
strings

Since we require grabbers and xmltv files to be XMLTV compliant the
TimeOffset setting makes no sense and is only likely to cause
mis-configurations.

The date string parsing has been improved to handling more legitimate
strings and leverages QDateTimes parsing instead of duplicating it.
  • Loading branch information...
stuartm committed Apr 3, 2013
1 parent 7683a3e commit ff5ab27842c522f9e054876a8eb69a51b8c86a2e
@@ -116,44 +116,12 @@ ChannelInfo *XMLTVParser::parseChannel(QDomElement &element, QUrl &baseUrl)
return chaninfo;
}
-static int TimezoneToInt (QString timezone)
+static void fromXMLTVDate(QString &timestr, QDateTime &dt)
{
- // we signal an error by setting it invalid (> 840min = 14hr)
- int result = 841;
+ // The XMLTV spec requires dates to either be in UTC/GMT or to specify a
+ // valid timezone. We are sticking to the spec and require all grabbers
+ // to comply.
- if (timezone.toUpper() == "UTC" || timezone.toUpper() == "GMT")
- return 0;
-
- if (timezone.length() == 5)
- {
- bool ok;
-
- result = timezone.mid(1,2).toInt(&ok, 10);
-
- if (!ok)
- result = 841;
- else
- {
- result *= 60;
-
- int min = timezone.right(2).toInt(&ok, 10);
-
- if (!ok)
- result = 841;
- else
- {
- result += min;
- if (timezone.left(1) == "-")
- result *= -1;
- }
- }
- }
- return result;
-}
-
-// localTimezoneOffset: 841 == "None", -841 == "Auto", other == fixed offset
-static void fromXMLTVDate(QString &timestr, QDateTime &dt, int localTimezoneOffset = 841)
-{
if (timestr.isEmpty())
{
LOG(VB_XMLTV, LOG_ERR, "Found empty Date/Time in XMLTV data, ignoring");
@@ -162,62 +130,76 @@ static void fromXMLTVDate(QString &timestr, QDateTime &dt, int localTimezoneOffs
QStringList split = timestr.split(" ");
QString ts = split[0];
- bool ok;
- int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
+ QDateTime tmpDT;
+ tmpDT.setTimeSpec(Qt::LocalTime);
+ // UTC/GMT, just strip
+ if (ts.endsWith('Z'))
+ ts.truncate(ts.length()-1);
+
if (ts.length() == 14)
{
- year = ts.left(4).toInt(&ok, 10);
- month = ts.mid(4,2).toInt(&ok, 10);
- day = ts.mid(6,2).toInt(&ok, 10);
- hour = ts.mid(8,2).toInt(&ok, 10);
- min = ts.mid(10,2).toInt(&ok, 10);
- sec = ts.mid(12,2).toInt(&ok, 10);
+ tmpDT = QDateTime::fromString(ts, "yyyyMMddHHmmss");
}
else if (ts.length() == 12)
{
- year = ts.left(4).toInt(&ok, 10);
- month = ts.mid(4,2).toInt(&ok, 10);
- day = ts.mid(6,2).toInt(&ok, 10);
- hour = ts.mid(8,2).toInt(&ok, 10);
- min = ts.mid(10,2).toInt(&ok, 10);
- sec = 0;
+ tmpDT = QDateTime::fromString(ts, "yyyyMMddHHmm");
}
- else
+ else if (ts.length() == 8)
+ {
+ tmpDT = QDateTime::fromString(ts, "yyyyMMdd");
+ }
+ else if (ts.length() == 6)
+ {
+ tmpDT = QDateTime::fromString(ts, "yyyyMM");
+ }
+ else if (ts.length() == 4)
+ {
+ tmpDT = QDateTime::fromString(ts, "yyyy");
+ }
+
+ if (!tmpDT.isValid())
{
LOG(VB_GENERAL, LOG_ERR,
QString("Ignoring unknown timestamp format: %1")
.arg(ts));
return;
}
-
- dt = QDateTime(QDate(year, month, day),QTime(hour, min, sec),
- Qt::LocalTime);
-
- if ((split.size() > 1) && (localTimezoneOffset <= 840))
+
+ if (split.size() > 1)
{
QString tmp = split[1].trimmed();
-
- int ts_offset = TimezoneToInt(tmp);
- if (abs(ts_offset) > 840)
- {
- ts_offset = 0;
- localTimezoneOffset = 841;
- }
- dt = dt.addSecs(-ts_offset * 60);
+
+ // These shouldn't be required and they aren't ISO 8601 but the
+ // xmltv spec mentions these and just these so handle them just in
+ // case
+ if (tmp == "GMT" || tmp == "UTC")
+ tmp = "+0000";
+ else if (tmp == "BST")
+ tmp = "+0100";
+
+ // While this seems like a hack, it's better than what was done before
+ QString isoDateString = QString("%1 %2").arg(tmpDT.toString(Qt::ISODate))
+ .arg(tmp);
+ dt = QDateTime::fromString(isoDateString, Qt::ISODate).toUTC();
}
-
- if (localTimezoneOffset < -840)
+
+ if (!dt.isValid())
{
- dt.setTimeSpec(Qt::UTC);
- }
- else if (abs(localTimezoneOffset) <= 840)
- {
- dt = dt.addSecs(localTimezoneOffset * 60 );
+ static bool warned_once_on_implicit_utc = false;
+ if (!warned_once_on_implicit_utc)
+ {
+ LOG(VB_XMLTV, LOG_ERR, "No explicit time zone found, "
+ "guessing implicit UTC! Please consider enhancing "
+ "the guide source to provice explicit UTC or local "
+ "time instead.");
+ warned_once_on_implicit_utc = true;
+ }
+ dt = tmpDT;
}
- dt = dt.toUTC();
-
+ dt.setTimeSpec(Qt::UTC);
+
timestr = MythDate::toString(dt, MythDate::kFilename);
}
@@ -286,19 +268,18 @@ static void parseAudio(QDomElement &element, ProgInfo *pginfo)
}
}
-ProgInfo *XMLTVParser::parseProgram(
- QDomElement &element, int localTimezoneOffset)
+ProgInfo *XMLTVParser::parseProgram(QDomElement &element)
{
QString uniqueid, season, episode;
int dd_progid_done = 0;
ProgInfo *pginfo = new ProgInfo();
QString text = element.attribute("start", "");
- fromXMLTVDate(text, pginfo->starttime, localTimezoneOffset);
+ fromXMLTVDate(text, pginfo->starttime);
pginfo->startts = text;
text = element.attribute("stop", "");
- fromXMLTVDate(text, pginfo->endtime, localTimezoneOffset);
+ fromXMLTVDate(text, pginfo->endtime);
pginfo->endts = text;
text = element.attribute("channel", "");
@@ -422,8 +403,7 @@ ProgInfo *XMLTVParser::parseProgram(
if (!prevdate.isEmpty())
{
QDateTime date;
- fromXMLTVDate(prevdate, date,
- localTimezoneOffset);
+ fromXMLTVDate(prevdate, date);
pginfo->originalairdate = date.date();
}
}
@@ -610,28 +590,6 @@ bool XMLTVParser::parseFile(
f.close();
- // now we calculate the localTimezoneOffset, so that we can fix
- // the programdata if needed
- QString config_offset = gCoreContext->GetSetting("TimeOffset", "None");
- // we disable this feature by setting it invalid (> 840min = 14hr)
- int localTimezoneOffset = 841;
-
- if (config_offset == "Auto")
- {
- // we mark auto with the -ve of the disable magic number
- localTimezoneOffset = -841;
- }
- else if (config_offset != "None")
- {
- localTimezoneOffset = TimezoneToInt(config_offset);
- if (abs(localTimezoneOffset) > 840)
- {
- LOG(VB_XMLTV, LOG_ERR, QString("Ignoring invalid TimeOffset %1")
- .arg(config_offset));
- localTimezoneOffset = 841;
- }
- }
-
QDomElement docElem = doc.documentElement();
QUrl baseUrl(docElem.attribute("source-data-url", ""));
@@ -664,7 +622,7 @@ bool XMLTVParser::parseFile(
}
else if (e.tagName() == "programme")
{
- ProgInfo *pginfo = parseProgram(e, localTimezoneOffset);
+ ProgInfo *pginfo = parseProgram(e);
if (pginfo->startts == pginfo->endts)
{
@@ -19,7 +19,7 @@ class XMLTVParser
XMLTVParser();
ChannelInfo *parseChannel(QDomElement &element, QUrl &baseUrl);
- ProgInfo *parseProgram(QDomElement &element, int localTimezoneOffset);
+ ProgInfo *parseProgram(QDomElement &element);
bool parseFile(QString filename, ChannelInfoList *chanlist,
QMap<QString, QList<ProgInfo> > *proglist);
@@ -273,90 +273,6 @@ static HostLineEdit *MiscStatusScript()
return he;
}
-static void init_time_offsets(GlobalComboBox *gc)
-{
- gc->addSelection("None");
- gc->addSelection("Auto");
- gc->addSelection("+0030");
- gc->addSelection("+0100");
- gc->addSelection("+0130");
- gc->addSelection("+0200");
- gc->addSelection("+0230");
- gc->addSelection("+0300");
- gc->addSelection("+0330");
- gc->addSelection("+0400");
- gc->addSelection("+0430");
- gc->addSelection("+0500");
- gc->addSelection("+0530");
- gc->addSelection("+0600");
- gc->addSelection("+0630");
- gc->addSelection("+0700");
- gc->addSelection("+0730");
- gc->addSelection("+0800");
- gc->addSelection("+0830");
- gc->addSelection("+0900");
- gc->addSelection("+0930");
- gc->addSelection("+1000");
- gc->addSelection("+1030");
- gc->addSelection("+1100");
- gc->addSelection("+1130");
- gc->addSelection("+1200");
- gc->addSelection("-1100");
- gc->addSelection("-1030");
- gc->addSelection("-1000");
- gc->addSelection("-0930");
- gc->addSelection("-0900");
- gc->addSelection("-0830");
- gc->addSelection("-0800");
- gc->addSelection("-0730");
- gc->addSelection("-0700");
- gc->addSelection("-0630");
- gc->addSelection("-0600");
- gc->addSelection("-0530");
- gc->addSelection("-0500");
- gc->addSelection("-0430");
- gc->addSelection("-0400");
- gc->addSelection("-0330");
- gc->addSelection("-0300");
- gc->addSelection("-0230");
- gc->addSelection("-0200");
- gc->addSelection("-0130");
- gc->addSelection("-0100");
- gc->addSelection("-0030");
-}
-
-static GlobalComboBox *TimeOffset()
-{
- GlobalComboBox *gc = new GlobalComboBox("TimeOffset");
- gc->setLabel(QObject::tr("Your local time zone (for XMLTV)"));
- init_time_offsets(gc);
- QString helptext = QObject::tr(
- "Used if the XMLTV data comes from a different time zone than your "
- "own and modifies the date and time before insertion into the "
- "database. 'Auto' converts the XMLTV time to local time using your "
- "computer's time zone. "
- "'None' ignores the XMLTV time zone, interpreting times as local.");
- gc->setHelpText(helptext);
- return gc;
-};
-
-#if 0
-static GlobalComboBox *EITTimeOffset()
-{
- GlobalComboBox *gc = new GlobalComboBox("EITTimeOffset");
- gc->setLabel(QObject::tr("Time offset for EIT listings"));
- init_time_offsets(gc);
- gc->setValue(1);
- QString helptext = QObject::tr(
- "Adjust the relative time zone of the EIT EPG data. "
- "'Auto' converts the EIT time to local time using your "
- "computer's time zone. "
- "'None' ignores the EIT time zone, interpreting times as local.");
- gc->setHelpText(helptext);
- return gc;
-};
-#endif
-
static GlobalSpinBox *EITTransportTimeout()
{
GlobalSpinBox *gc = new GlobalSpinBox("EITTransportTimeout", 1, 15, 1);
@@ -918,7 +834,6 @@ BackendSettings::BackendSettings() {
locale->addChild(TVFormat());
locale->addChild(VbiFormat());
locale->addChild(FreqTable());
- locale->addChild(TimeOffset());
addChild(locale);
VerticalConfigurationGroup* group2 = new VerticalConfigurationGroup(false);
@@ -947,7 +862,6 @@ BackendSettings::BackendSettings() {
VerticalConfigurationGroup* group2a1 = new VerticalConfigurationGroup(false);
group2a1->setLabel(QObject::tr("EIT Scanner Options"));
- //group2a1->addChild(EITTimeOffset());
group2a1->addChild(EITTransportTimeout());
group2a1->addChild(EITCrawIdleStart());
addChild(group2a1);

0 comments on commit ff5ab27

Please sign in to comment.