Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Foundation/src/DateTimeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,36 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat
}
// Skip trailing whitespace
while (it != end && Ascii::isSpace(*it)) ++it;
// Skip optional fractional seconds ('.NNN' or '.NNNNNN') left unconsumed
// when the format used %S (integer seconds) but the input contains sub-second
// precision (e.g. "2013-10-07 08:23:19.120-04:00" parsed with ISO8601_FORMAT
// which uses %S not %s).
if (it != end && (*it == '.' || *it == ','))
{
auto savedIt = it;
++it; // skip the separator
if (it != end && Ascii::isDigit(*it))
{
while (it != end && Ascii::isDigit(*it)) ++it; // skip digits
}
else
{
it = savedIt; // no digits after separator - not fractional seconds
}
}
// Skip optional trailing timezone designator (e.g. 'Z', '+04:00', '-04:00',
// named zones such as 'GMT') for compatibility with ISO 8601, RFC 3339 and
// ASN.1 UTCTime/GeneralizedTime formats that carry timezone information not
// matched by the format string. Use parseTZD() so that all recognised TZD
// patterns are consumed; restore the iterator if parseTZD throws (unknown or
// partially-parsed designator) so that the trailing-garbage check below still
// catches truly invalid suffixes.
if (it != end && (*it == 'Z' || *it == 'z' || *it == '+' || *it == '-' || Ascii::isAlpha(*it)))
{
auto savedIt = it;
try { parseTZD(it, end); }
catch (...) { it = savedIt; }
}
// Check for unconsumed input
if (it != end)
throw SyntaxException("Invalid DateTimeString: " + dtStr + ", unexpected trailing characters");
Expand Down
45 changes: 44 additions & 1 deletion Foundation/src/Timezone_UNIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
#include <mutex>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <string>
#include <sys/stat.h>


namespace Poco {
Expand Down Expand Up @@ -66,13 +68,52 @@ class TZInfo
{
const char* tz = std::getenv("TZ");
_cachedTZ = tz ? tz : "";
cacheLocaltimeStat();
}

bool tzChanged() const
{
const char* tz = std::getenv("TZ");
std::string currentTZ = tz ? tz : "";
return currentTZ != _cachedTZ;
if (currentTZ != _cachedTZ) return true;
return localtimeStatChanged();
}

void cacheLocaltimeStat()
{
struct stat st{};
if (::stat("/etc/localtime", &st) == 0)
{
_localtime_ino = st.st_ino;
_localtime_mtime = st.st_mtime;
}
else
{
_localtime_ino = 0;
_localtime_mtime = 0;
}
}

bool localtimeStatChanged() const
{
struct stat st{};
if (::stat("/etc/localtime", &st) == 0)
{
if (st.st_ino != _localtime_ino || st.st_mtime != _localtime_mtime)
{
_localtime_ino = st.st_ino;
_localtime_mtime = st.st_mtime;
return true;
}
return false;
}
// /etc/localtime not accessible: treat as changed only if we had it before
if (_localtime_ino != 0) {
_localtime_ino = 0;
_localtime_mtime = 0;
return true;
}
return false;
}

static int computeTimeZone()
Expand Down Expand Up @@ -112,6 +153,8 @@ class TZInfo
std::mutex _mutex;
int _tzOffset;
std::string _cachedTZ;
mutable ino_t _localtime_ino = 0;
mutable time_t _localtime_mtime = 0;
};


Expand Down
Loading