diff --git a/pvr.iptvsimple/addon.xml.in b/pvr.iptvsimple/addon.xml.in index a5b6af016..14d14456a 100644 --- a/pvr.iptvsimple/addon.xml.in +++ b/pvr.iptvsimple/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ diff --git a/pvr.iptvsimple/changelog.txt b/pvr.iptvsimple/changelog.txt index 6fa5db94a..06b3b2ada 100644 --- a/pvr.iptvsimple/changelog.txt +++ b/pvr.iptvsimple/changelog.txt @@ -1,3 +1,5 @@ +v3.5.8 +- Fix wrong EPG times due to DST on Windows v3.5.7 - Correctly show build version in Kodi diff --git a/src/PVRIptvData.cpp b/src/PVRIptvData.cpp index a8376bf1a..7e6133ad5 100644 --- a/src/PVRIptvData.cpp +++ b/src/PVRIptvData.cpp @@ -77,6 +77,57 @@ inline bool GetAttributeValue(const xml_node * pNode, const char* strAttribu return true; } +namespace +{ + +// Adapted from https://stackoverflow.com/a/31533119 + +// Conversion from UTC date to second, signed 64-bit adjustable epoch version. +// Written by François Grieu, 2015-07-21; public domain. + +long long MakeTime(int year, int month, int day) +{ + return static_cast(year) * 365 + year / 4 - year / 100 * 3 / 4 + (month + 2) * 153 / 5 + day; +} + +long long GetUTCTime(int year, int mon, int mday, int hour, int min, int sec) +{ + int m = mon - 1; + int y = year + 100; + + if (m < 2) + { + m += 12; + --y; + } + + return (((MakeTime(y, m, mday) - MakeTime(1970 + 99, 12, 1)) * 24 + hour) * 60 + min) * 60 + sec; +} + +long long ParseDateTime(const std::string& strDate) +{ + int year = 2000; + int mon = 1; + int mday = 1; + int hour = 0; + int min = 0; + int sec = 0; + char offset_sign = '+'; + int offset_hours = 0; + int offset_minutes = 0; + + sscanf(strDate.c_str(), "%04d%02d%02d%02d%02d%02d %c%02d%02d", &year, &mon, &mday, &hour, &min, &sec, &offset_sign, &offset_hours, &offset_minutes); + + long offset_of_date = (offset_hours * 60 + offset_minutes) * 60; + if (offset_sign == '-') + offset_of_date = -offset_of_date; + + return GetUTCTime(year, mon, mday, hour, min, sec) - offset_of_date; +} + +} // unnamed namespace + + PVRIptvData::PVRIptvData(void) { m_strXMLTVUrl = g_strTvgPath; @@ -262,8 +313,8 @@ bool PVRIptvData::LoadEPG(time_t iStart, time_t iEnd) || !GetAttributeValue(pChannelNode, "stop", strStop)) continue; - int iTmpStart = ParseDateTime(strStart); - int iTmpEnd = ParseDateTime(strStop); + long long iTmpStart = ParseDateTime(strStart); + long long iTmpEnd = ParseDateTime(strStop); if ( (iTmpEnd + iMaxShiftTime < iStart) || (iTmpStart + iMinShiftTime > iEnd)) @@ -275,8 +326,8 @@ bool PVRIptvData::LoadEPG(time_t iStart, time_t iEnd) entry.iGenreType = 0; entry.iGenreSubType = 0; entry.strPlotOutline = ""; - entry.startTime = iTmpStart; - entry.endTime = iTmpEnd; + entry.startTime = static_cast(iTmpStart); + entry.endTime = static_cast(iTmpEnd); GetNodeValue(pChannelNode, "title", entry.strTitle); GetNodeValue(pChannelNode, "desc", entry.strPlot); @@ -805,41 +856,6 @@ int PVRIptvData::GetFileContents(std::string& url, std::string &strContent) return strContent.length(); } -int PVRIptvData::ParseDateTime(std::string& strDate, bool iDateFormat) -{ - struct tm timeinfo; - memset(&timeinfo, 0, sizeof(tm)); - char sign = '+'; - int hours = 0; - int minutes = 0; - - if (iDateFormat) - sscanf(strDate.c_str(), "%04d%02d%02d%02d%02d%02d %c%02d%02d", &timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday, &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec, &sign, &hours, &minutes); - else - sscanf(strDate.c_str(), "%02d.%02d.%04d%02d:%02d:%02d", &timeinfo.tm_mday, &timeinfo.tm_mon, &timeinfo.tm_year, &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec); - - timeinfo.tm_mon -= 1; - timeinfo.tm_year -= 1900; - timeinfo.tm_isdst = -1; - - std::time_t current_time; - std::time(¤t_time); - long offset = 0; -#ifndef TARGET_WINDOWS - offset = -std::localtime(¤t_time)->tm_gmtoff; -#else - _get_timezone(&offset); -#endif // TARGET_WINDOWS - - long offset_of_date = (hours * 60 * 60) + (minutes * 60); - if (sign == '-') - { - offset_of_date = -offset_of_date; - } - - return mktime(&timeinfo) - offset_of_date - offset; -} - PVRIptvChannel * PVRIptvData::FindChannel(const std::string &strId, const std::string &strName) { std::string strTvgName = strName; diff --git a/src/PVRIptvData.h b/src/PVRIptvData.h index 0523364b2..33cb73a82 100644 --- a/src/PVRIptvData.h +++ b/src/PVRIptvData.h @@ -110,7 +110,6 @@ class PVRIptvData : public P8PLATFORM::CThread virtual PVRIptvEpgChannel* FindEpg(const std::string &strId); virtual PVRIptvEpgChannel* FindEpgForChannel(PVRIptvChannel &channel); virtual bool FindEpgGenre(const std::string& strGenre, int& iType, int& iSubType); - virtual int ParseDateTime(std::string& strDate, bool iDateFormat = true); virtual bool GzipInflate( const std::string &compressedBytes, std::string &uncompressedBytes); virtual int GetCachedFileContents(const std::string &strCachedName, const std::string &strFilePath, std::string &strContent, const bool bUseCache = false);