Added Time methods used to encode to and parse from string containing internet/javascript date and time.
git-svn-id: http://voip.null.ro/svn/yate@6364 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
6b2daa2d48
commit
e7c575815e
|
@ -867,6 +867,114 @@ uint32_t Time::fromNtp(uint32_t val, uint32_t* under, bool rfc2030)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned int Time::toString(char* buf, uint64_t time, int frac)
|
||||
{
|
||||
if (!buf)
|
||||
return 0;
|
||||
int y;
|
||||
unsigned int m,d,hh,mm,ss;
|
||||
if (!Time::toDateTime(time / 1000000,y,m,d,hh,mm,ss) || y < 0 || y > 9999)
|
||||
return 0;
|
||||
unsigned int n = 0;
|
||||
if (!frac)
|
||||
n = ::sprintf(buf,"%04d-%02u-%02uT%02u:%02u:%02u",y,m,d,hh,mm,ss);
|
||||
else {
|
||||
unsigned int f = time % 1000000;
|
||||
if (frac > 0)
|
||||
n = ::sprintf(buf,"%04d-%02u-%02uT%02u:%02u:%02u.%03u",y,m,d,hh,mm,ss,f / 1000);
|
||||
else
|
||||
n = ::sprintf(buf,"%04d-%02u-%02uT%02u:%02u:%02u.%06u",y,m,d,hh,mm,ss,f);
|
||||
}
|
||||
if (n)
|
||||
buf[n++] = 'Z';
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline bool addNum2(const char* buf, unsigned int& val, unsigned int maxVal = 0)
|
||||
{
|
||||
if (buf[0] < '0' || buf[0] > '9' || buf[1] < '0' || buf[1] > '9')
|
||||
return false;
|
||||
val += 10 * (buf[0] - '0') + (buf[1] - '0');
|
||||
return !maxVal || val <= maxVal;
|
||||
}
|
||||
|
||||
// Decode yyyy-mm-dd{T|t}hh:mm:ss[.SEC-FRAC]{{Z|z}|{+/-hh:mm}}
|
||||
uint64_t Time::toEpoch(const char* buf, unsigned int len, int frac)
|
||||
{
|
||||
if (!buf)
|
||||
return (uint64_t)-1;
|
||||
if (!len)
|
||||
len = ::strlen(buf);
|
||||
if (len < 20)
|
||||
return (uint64_t)-1;
|
||||
// Check mandatory yyyy-mm-ddThh:mm:ss
|
||||
if (buf[4] != '-' || buf[7] != '-' || (buf[10] != 'T' && buf[10] != 't')
|
||||
|| buf[13] != ':' || buf[16] != ':')
|
||||
return (uint64_t)-1;
|
||||
int offsetSec = 0;
|
||||
unsigned int delta = 0;
|
||||
if (buf[19] != 'Z' && buf[19] != 'z') {
|
||||
// We must receive at least '.' + digit + 'Z' or TZ offset
|
||||
if (len < 22)
|
||||
return (uint64_t)-1;
|
||||
unsigned int crt = 19;
|
||||
// Second fraction ?
|
||||
if (buf[19] == '.') {
|
||||
for (crt++; crt < len; crt++) {
|
||||
if (buf[crt] < '0' || buf[crt] > '9')
|
||||
break;
|
||||
}
|
||||
unsigned int fracLen = crt - 20;
|
||||
// Empty fraction or buffer end
|
||||
if (!fracLen || crt == len)
|
||||
return (uint64_t)-1;
|
||||
if (frac) {
|
||||
unsigned int req = frac > 0 ? 3 : 6;
|
||||
String tmp(buf + 20,fracLen > req ? req : fracLen);
|
||||
delta = tmp.toInteger(0,10);
|
||||
for (; fracLen < req; ++fracLen)
|
||||
delta *= 10;
|
||||
}
|
||||
}
|
||||
// TZ offset: ('+' / '-')hh:mm
|
||||
if (buf[crt] != 'Z' && buf[crt] != 'z') {
|
||||
const char* b = buf + crt;
|
||||
unsigned int tzOffsLen = len - crt;
|
||||
if (tzOffsLen != 6 || b[3] != ':')
|
||||
return (uint64_t)-1;
|
||||
int mul = 1;
|
||||
if (*b == '-')
|
||||
mul = -1;
|
||||
else if (*b != '+')
|
||||
return (uint64_t)-1;
|
||||
unsigned int hh = 0, mm = 0;
|
||||
if (!(addNum2(b + 1,hh,23) && addNum2(b + 4,mm,59)))
|
||||
return (uint64_t)-1;
|
||||
offsetSec = mul * (int)(hh * 3600 + mm * 60);
|
||||
}
|
||||
}
|
||||
unsigned int y = 0, m = 0, d = 0, hh = 0, mm = 0, ss = 0;
|
||||
if (!addNum2(buf,y))
|
||||
return (uint64_t)-1;
|
||||
y *= 100;
|
||||
if (!(addNum2(buf + 2,y) && (addNum2(buf + 5,m,12) || !m) && (addNum2(buf + 8,d,31) || !d)
|
||||
&& addNum2(buf + 11,hh,23) && addNum2(buf + 14,mm,59) && addNum2(buf + 17,ss,60)))
|
||||
return (uint64_t)-1;
|
||||
bool leapSec = (ss == 60);
|
||||
if (leapSec)
|
||||
ss = 59;
|
||||
uint64_t sec = toEpoch(y,m,d,hh,mm,ss,offsetSec);
|
||||
if (sec == (unsigned int)-1)
|
||||
return (uint64_t)-1;
|
||||
if (leapSec)
|
||||
sec++;
|
||||
if (!frac)
|
||||
return sec;
|
||||
if (frac > 0)
|
||||
return sec * 1000 + delta;
|
||||
return sec * 1000000 + delta;
|
||||
}
|
||||
|
||||
int Time::timeZone()
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
|
43
yateclass.h
43
yateclass.h
|
@ -3867,6 +3867,49 @@ public:
|
|||
*/
|
||||
static uint32_t fromNtp(uint32_t val, uint32_t* under = 0, bool rfc2030 = true);
|
||||
|
||||
/**
|
||||
* Convert EPOCH time to a string representation. Does not add a NUL char at end
|
||||
* Minimal representation is yyyy-mm-ddThh:mm:ssZ
|
||||
* Destination buffer length must be at least 20 if no fractions are going to be filled
|
||||
* For milliseconds fractions extra 4 bytes must be available in buffer
|
||||
* For microseconds fractions extra 7 bytes must be available in buffer
|
||||
* @param buf Buffer to be filled
|
||||
* @param time System time in microseconds to convert
|
||||
* @param frac Add second fractions. 0: none, negative: microseconds, positive: milliseconds
|
||||
* @return The number of chars written in buffer. 0 on failure
|
||||
*/
|
||||
static unsigned int toString(char* buf, uint64_t time, int frac = 0);
|
||||
|
||||
/**
|
||||
* Convert system time to a string representation
|
||||
* Minimal representation is yyyy-mm-ddThh:mm:ssZ
|
||||
* Destination buffer length must be at least 20 if no fractions are going to be filled
|
||||
* For milliseconds fractions extra 4 bytes must be available in buffer
|
||||
* For microseconds fractions extra 7 bytes must be available in buffer
|
||||
* @param buf Buffer to append to
|
||||
* @param time System time in microseconds to convert
|
||||
* @param frac Add second fractions. 0: none, negative: microseconds, positive: milliseconds
|
||||
* @return The number of chars added to buffer. 0 on failure
|
||||
*/
|
||||
static inline unsigned int appendTo(String& buf, uint64_t time, int frac = 0) {
|
||||
char tmp[30];
|
||||
unsigned int n = toString(tmp,time,frac);
|
||||
if (n)
|
||||
buf.append(tmp,n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode string to EPOCH time
|
||||
* Decode yyyy-mm-dd{T|t}hh:mm:ss[.SEC-FRAC]{{Z|z}|{+/-hh:mm}}
|
||||
* Date seconds may contain leap seconds (value 60). These are ignored (second will be used as 59)
|
||||
* @param buf Buffer to parse
|
||||
* @param len Buffer length. 0 to detect
|
||||
* @param frac Handle second fractions. 0: none, negative: microseconds, positive: milliseconds
|
||||
* @return EPOCH time in (milli|micro)seconds, -1 on failure
|
||||
*/
|
||||
static uint64_t toEpoch(const char* buf, unsigned int len, int frac = 0);
|
||||
|
||||
/**
|
||||
* Check if an year is a leap one
|
||||
* @param year The year to check
|
||||
|
|
Loading…
Reference in New Issue