2019-01-29 Fred Gleason <fredg@paravelsystems.com>

* Refactored routines for parsing/writing standard date/time strings
	(RFC822 and XML xs:dateTime formats) into 'lib/rddatetime.[cpp|h].
	* Removed the 'RDWebDateTime()', 'RDGetWebDateTime()',
	'RDGetWebDate()', 'RDGetWebTime()', 'RDGetWebMonth()',
	'RDXmlDate()', 'RDXmlTime()', 'RDXmlDateTime()' and
	'RDXmlTimeZoneSuffix()' functions from 'lib/rdweb.[cpp|h].
	* Added a 'dateparse_test' test harness.
This commit is contained in:
Fred Gleason
2019-01-29 15:40:14 -05:00
parent 16d43261a3
commit 0b472716d6
15 changed files with 733 additions and 349 deletions

View File

@@ -107,6 +107,7 @@ dist_librd_la_SOURCES = dbversion.h\
rddatepicker.cpp rddatepicker.h\
rddb.h rddb.cpp\
rddbheartbeat.cpp rddbheartbeat.h\
rddatetime.cpp rddatetime.h\
rddebug.cpp rddebug.h\
rddeck.cpp rddeck.h\
rddelete.cpp rddelete.h\

View File

@@ -74,6 +74,7 @@ SOURCES += rdcut_dialog.cpp
SOURCES += rddatedialog.cpp
SOURCES += rddatedecode.cpp
SOURCES += rddatepicker.cpp
SOURCES += rddatetime.cpp
SOURCES += rddb.cpp
SOURCES += rddbheartbeat.cpp
SOURCES += rddebug.cpp
@@ -204,6 +205,7 @@ HEADERS += rdcut.h
HEADERS += rddatedecode.h
HEADERS += rddatedialog.h
HEADERS += rddatepicker.h
HEADERS += rddatetime.h
HEADERS += rddb.h
HEADERS += rddbheartbeat.h
HEADERS += rddebug.h

View File

@@ -37,9 +37,10 @@
#include <sys/timex.h>
#include <time.h>
#include <rddb.h>
#include <rdconf.h>
#include <rdescape_string.h>
#include "rddb.h"
#include "rdconf.h"
#include "rddatetime.h"
#include "rdescape_string.h"
#define BUFFER_SIZE 1024
@@ -982,7 +983,7 @@ QTime RDUtcToLocal(const QTime &gmttime)
return gmttime.addSecs(-RDTimeZoneOffset());
}
/*
int RDTimeZoneOffset()
{
time_t t=time(&t);
@@ -1001,7 +1002,7 @@ int RDTimeZoneOffset()
return offset;
}
*/
QColor RDGetTextColor(const QColor &background_color)
{

View File

@@ -101,7 +101,7 @@ QDateTime RDLocalToUtc(const QDateTime &localdatetime);
QTime RDLocalToUtc(const QTime &localtime);
QDateTime RDUtcToLocal(const QDateTime &gmtdatetime);
QTime RDUtcToLocal(const QTime &gmttime);
int RDTimeZoneOffset();
//int RDTimeZoneOffset();
QColor RDGetTextColor(const QColor &background_color);
bool RDProcessActive(const QString &cmd);
bool RDProcessActive(const QStringList &cmds);

360
lib/rddatetime.cpp Normal file
View File

@@ -0,0 +1,360 @@
// rddatetime.cpp
//
// Parse and write dates/times in various standard formats.
//
// (C) Copyright 2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <stdio.h>
#include <time.h>
#include <qmap.h>
#include <qstringlist.h>
#include "rddatetime.h"
QString __rddatetime_month_names[]=
{"Jan","Feb","Mar","Apr","Mar","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
QString __rddatetime_dow_names[]=
{"Mod","Tue","Wed","Thu","Fri","Sat","Sun"};
//
// Auto-detect the format (XML xs:dateTime or RFC822)
//
QDateTime RDParseDateTime(const QString &str,bool *ok)
{
if(str.trimmed().contains(" ")) {
return RDParseRfc822DateTime(str,ok);
}
return RDParseXmlDateTime(str,ok);
}
//
// XML xs:date format
//
QDate RDParseXmlDate(const QString &str,bool *ok)
{
QDate ret=QDate::fromString(str,"yyyy-MM-dd");
*ok=ret.isValid();
return ret;
}
QString RDWriteXmlDate(const QDate &date)
{
return date.toString("yyyy-MM-dd");
}
//
// XML xs:time format
//
QTime RDParseXmlTime(const QString &str,bool *ok,int *day_offset)
{
QTime ret;
QStringList f0;
QStringList f1;
QStringList f2;
int tz=0;
QTime time;
QTime tztime;
*ok=false;
if(day_offset!=NULL) {
*day_offset=0;
}
f0=str.trimmed().split(" ");
if(f0.size()!=1) {
*ok=false;
return ret;
}
if(f0[0].right(1).lower()=="z") { // GMT
tz=RDTimeZoneOffset();
f0[0]=f0[0].left(f0[0].length()-1);
f2=f0[0].split(":");
}
else {
f1=f0[0].split("+");
if(f1.size()==2) { // GMT+
f2=f1[1].split(":");
if(f2.size()==2) {
tztime=QTime(f2[0].toInt(),f2[1].toInt(),0);
if(tztime.isValid()) {
tz=RDTimeZoneOffset()+QTime(0,0,0).secsTo(tztime);
}
}
else {
if(ok!=NULL) {
*ok=false;
}
return QTime();
}
}
else {
f1=f0[0].split("-");
if(f1.size()==2) { // GMT-
f2=f1[1].split(":");
if(f2.size()==2) {
tztime=QTime(f2[0].toInt(),f2[1].toInt(),0);
if(tztime.isValid()) {
tz=RDTimeZoneOffset()-QTime(0,0,0).secsTo(tztime);
}
}
else {
if(ok!=NULL) {
*ok=false;
}
return QTime();
}
}
}
f2=f1[0].split(":");
}
if(f2.size()==3) {
QStringList f3=f2[2].split(".");
time=QTime(f2[0].toInt(),f2[1].toInt(),f2[2].toInt());
if(time.isValid()) {
ret=time.addSecs(tz);
if(day_offset!=NULL) {
if((tz<0)&&((3600*time.hour()+60*time.minute()+time.second())<(-tz))) {
*day_offset=-1;
}
if((tz>0)&&(86400-((3600*time.hour()+60*time.minute()+time.second()))<tz)) {
*day_offset=1;
}
}
if(ok!=NULL) {
*ok=true;
}
}
}
return ret;
}
QString RDWriteXmlTime(const QTime &time)
{
int utc_off=RDTimeZoneOffset();
QString tz_str="-";
if(utc_off<0) {
tz_str="+";
}
tz_str+=QString().
sprintf("%02d:%02d",utc_off/3600,(utc_off-3600*(utc_off/3600))/60);
return time.toString("hh:mm:ss")+tz_str;
}
//
// XML xs:dateTime format
//
QDateTime RDParseXmlDateTime(const QString &str,bool *ok)
{
QDateTime ret;
QStringList list;
QStringList f0;
QStringList f1;
QStringList f2;
int day;
int month;
int year;
QTime time;
bool lok=false;
int day_offset=0;
*ok=false;
f0=str.trimmed().split(" ");
if(f0.size()!=1) {
*ok=false;
return ret;
}
f1=f0[0].split("T");
if(f1.size()<=2) {
f2=f1[0].split("-");
if(f2.size()==3) {
year=f2[0].toInt(&lok);
if(lok&&(year>0)) {
month=f2[1].toInt(&lok);
if(lok&&(month>=1)&&(month<=12)) {
day=f2[2].toInt(&lok);
if(lok&&(day>=1)&&(day<=31)) {
if(f1.size()==2) {
time=RDParseXmlTime(f1[1],&lok,&day_offset);
if(lok) {
ret=QDateTime(QDate(year,month,day),time).addDays(day_offset);
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
}
}
}
return ret;
}
QString RDWriteXmlDateTime(const QDateTime &dt)
{
return RDWriteXmlDate(dt.date())+"T"+RDWriteXmlTime(dt.time());
}
//
// RFC822 date/time format
//
QDateTime RDParseRfc822DateTime(const QString &str,bool *ok)
{
QStringList f0=str.trimmed().split(" ",QString::SkipEmptyParts);
//
// Remove useless day-of-the-week tag
//
if(f0.size()==6) {
f0.removeFirst();
}
if(f0.size()!=5) {
*ok=false;
return QDateTime();
}
//
// Read Date
//
int month=-1;
for(int i=0;i<7;i++) {
if(f0.at(1).toLower()==__rddatetime_month_names[i].toLower()) {
month=i;
}
}
if(month<0) {
*ok=false;
return QDateTime();
}
if(f0.at(2).length()==2) {
f0[2]="19"+f0.at(2);
}
QDate date(f0.at(2).toInt(),month+1,f0.at(0).toInt());
if(!date.isValid()) {
*ok=false;
return QDateTime();
}
//
// Read Time
//
QTime time=QTime::fromString(f0.at(3),"hh:mm:ss");
if(!time.isValid()) {
*ok=false;
return QDateTime();
}
//
// Read TZ Offset
//
bool ok1=false;
bool ok2=false;
int tz_offset=3600*f0.at(4).mid(1,2).toInt(&ok1)+
60*f0.at(4).right(2).toInt(&ok2);
if((f0.at(4).length()==5)&&(ok1)&&(ok2)) {
if(f0.at(4).left(1)=="+") {
tz_offset=-tz_offset;
}
else {
if(f0.at(4).left(1)!="-") {
*ok=false;
return QDateTime();
}
}
}
else {
//
// Try legacy timezone names (see RFC822 section 5.1)
//
QMap<QString,int> zones;
zones["ut"]=0;
zones["gmt"]=0;
zones["z"]=0;
zones["est"]=-5;
zones["edt"]=-4;
zones["cst"]=-6;
zones["cdt"]=-5;
zones["mst"]=-7;
zones["mdt"]=-6;
zones["pst"]=-8;
zones["pdt"]=-7;
// "Military" zone IDs are not implemented (see RFC1123 section 5.2.14)
if(zones.value(f0.at(4).toLower(),1)>0) {
*ok=false;
return QDateTime();
}
tz_offset=-3600*zones.value(f0.at(4).toLower());
}
*ok=true;
return QDateTime(date,time).addSecs(tz_offset-RDTimeZoneOffset());
}
QString RDWriteRfc822DateTime(const QDateTime &dt)
{
int utc_off=RDTimeZoneOffset();
QString tz_str="-";
if(utc_off<0) {
tz_str="+";
}
tz_str+=QString().
sprintf("%02d%02d",utc_off/3600,(utc_off-3600*(utc_off/3600))/60);
return __rddatetime_dow_names[dt.date().dayOfWeek()-1]+", "+
QString().sprintf("%d ",dt.date().day())+
__rddatetime_month_names[dt.date().month()-1]+" "+
QString().sprintf("%04d ",dt.date().year())+
dt.toString("hh:mm:ss")+" "+
tz_str;
}
//
// Returns the UTC offset of the curently configured timezone (seconds)
//
int RDTimeZoneOffset()
{
time_t t=time(&t);
struct tm *tm=localtime(&t);
time_t local_time=3600*tm->tm_hour+60*tm->tm_min+tm->tm_sec;
tm=gmtime(&t);
time_t gmt_time=3600*tm->tm_hour+60*tm->tm_min+tm->tm_sec;
int offset=gmt_time-local_time;
if(offset>43200) {
offset=offset-86400;
}
if(offset<-43200) {
offset=offset+86400;
}
return offset;
}

66
lib/rddatetime.h Normal file
View File

@@ -0,0 +1,66 @@
// rddatetime.h
//
// Parse and write dates/times in various standard formats.
//
// (C) Copyright 2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDDATETIME_H
#define RDDATETIME_H
#include <qstring.h>
#include <qdatetime.h>
//
// Function Prototypes
//
//
// Auto-detect the format (XML xs:dateTime or RFC822)
//
QDateTime RDParseDateTime(const QString &str,bool *ok);
//
// XML xs:date format
//
QDate RDParseXmlDate(const QString &str,bool *ok);
QString RDWriteXmlDate(const QDate &date);
//
// XML xs:time format
//
QTime RDParseXmlTime(const QString &str,bool *ok,int *day_offset=NULL);
QString RDWriteXmlTime(const QTime &time);
//
// XML xs:dateTime format
//
QDateTime RDParseXmlDateTime(const QString &str,bool *ok);
QString RDWriteXmlDateTime(const QDateTime &dt);
//
// RFC822 date/time format
//
QDateTime RDParseRfc822DateTime(const QString &str,bool *ok);
QString RDWriteRfc822DateTime(const QDateTime &dt);
//
// Returns the UTC offset of the curently configured timezone (seconds)
//
int RDTimeZoneOffset();
#endif // RDDATETIME_H

View File

@@ -25,8 +25,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <rdconf.h>
#include <rdweb.h>
#include "rdconf.h"
#include "rddatetime.h"
#include "rdweb.h"
#include <rdformpost.h>
@@ -237,7 +238,7 @@ bool RDFormPost::getValue(const QString &name,QDateTime *datetime,bool *ok)
}
}
else {
*datetime=RDGetWebDateTime(str,ok);
*datetime=RDParseDateTime(str,ok);
}
return true;
}
@@ -257,7 +258,7 @@ bool RDFormPost::getValue(const QString &name,QDate *date,bool *ok)
*date=QDate();
}
else {
*date=RDGetWebDate(str,ok);
*date=RDParseXmlDate(str,ok);
}
return true;
}
@@ -277,7 +278,7 @@ bool RDFormPost::getValue(const QString &name,QTime *time,bool *ok)
*time=QTime();
}
else {
*time=RDGetWebTime(str,ok);
*time=RDParseXmlTime(str,ok);
}
return true;
}

View File

@@ -31,6 +31,7 @@
#include <qstringlist.h>
#include "rdconf.h"
#include "rddatetime.h"
#include "rddb.h"
#include "rdescape_string.h"
#include "rdtempdirectory.h"
@@ -932,7 +933,7 @@ QString RDXmlField(const QString &tag,const QDateTime &value,
str=" "+attrs;
}
if(value.isValid()) {
return QString("<")+tag+str+">"+RDXmlDateTime(value)+"</"+tag+">\n";
return QString("<")+tag+str+">"+RDWriteXmlDateTime(value)+"</"+tag+">\n";
}
return RDXmlField(tag);
}
@@ -946,7 +947,7 @@ QString RDXmlField(const QString &tag,const QDate &value,const QString &attrs)
str=" "+attrs;
}
if(value.isValid()&&(!value.isNull())) {
return QString("<")+tag+str+">"+RDXmlDate(value)+"</"+tag+">\n";
return QString("<")+tag+str+">"+RDWriteXmlDate(value)+"</"+tag+">\n";
}
return RDXmlField(tag);
}
@@ -960,7 +961,7 @@ QString RDXmlField(const QString &tag,const QTime &value,const QString &attrs)
str=" "+attrs;
}
if(value.isValid()&&(!value.isNull())) {
return QString("<")+tag+str+">"+RDXmlTime(value)+"</"+tag+">\n";
return QString("<")+tag+str+">"+RDWriteXmlTime(value)+"</"+tag+">\n";
}
return RDXmlField(tag);
}
@@ -972,47 +973,6 @@ QString RDXmlField(const QString &tag)
}
QString RDXmlDate(const QDate &date)
{
return date.toString("yyyy-MM-dd")+RDXmlTimeZoneSuffix();
}
QString RDXmlTime(const QTime &time)
{
return time.toString("hh:mm:ss")+RDXmlTimeZoneSuffix();
}
QString RDXmlDateTime(const QDateTime &datetime)
{
return datetime.toString("yyyy-MM-dd")+"T"+datetime.toString("hh:mm:ss")+
RDXmlTimeZoneSuffix();
}
QString RDXmlTimeZoneSuffix()
{
QString ret;
int tz=RDTimeZoneOffset();
if(tz==0) {
ret+="Z";
}
else {
if(tz<0) {
ret+="+";
}
if(tz>0) {
ret+="-";
}
ret+=QTime(0,0,0).addSecs(tz).toString("hh:mm");
}
return ret;
}
QString RDXmlEscape(const QString &str)
{
/*
@@ -1142,7 +1102,8 @@ QString RDJsonField(const QString &name,const QDateTime &value,int padding,
if(!value.isValid()) {
return RDJsonNullField(name,padding,final);
}
return RDJsonPadding(padding)+"\""+name+"\": \""+RDXmlDateTime(value)+"\""+
return RDJsonPadding(padding)+"\""+name+"\": \""+
RDWriteXmlDateTime(value)+"\""+
comma+"\r\n";
}
@@ -1192,284 +1153,3 @@ QString RDUrlUnescape(const QString &str)
return ret;
}
QString RDWebDateTime(const QDateTime &datetime)
{
//
// Generate an RFC 822/1123 compliant date/time string
//
if(!datetime.isValid()) {
return QString();
}
int offset=RDTimeZoneOffset();
QString tzstr="-";
if(offset<0) {
tzstr="+";
}
tzstr+=QString().sprintf("%02d%02d",
offset/3600,(offset/60)-((offset/3600)*60));
if(offset==0) {
tzstr="GMT";
}
return datetime.toString("ddd, dd MMM yyyy hh:mm:ss")+" "+tzstr;
}
QDateTime RDGetWebDateTime(const QString &str,bool *ok)
{
QDateTime ret;
QStringList list;
QStringList f0;
QStringList f1;
QStringList f2;
int day;
int month;
int year;
QTime time;
bool lok=false;
if(ok!=NULL) {
*ok=false;
}
f0=str.trimmed().split(" ");
switch(f0.size()) {
case 1: // XML xs:dateTime Style
f1=f0[0].split("T");
if(f1.size()<=2) {
f2=f1[0].split("-");
if(f2.size()==3) {
year=f2[0].toInt(&lok);
if(lok&&(year>0)) {
month=f2[1].toInt(&lok);
if(lok&&(month>=1)&&(month<=12)) {
day=f2[2].toInt(&lok);
if(lok&&(day>=1)&&(day<=31)) {
if(f1.size()==2) {
time=RDGetWebTime(f1[1],&lok);
if(lok) {
ret=QDateTime(QDate(year,month,day),time);
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
}
}
}
break;
case 4: // RFC 850 Style
f1=f0[1].split("-");
if(f1.size()==3) {
month=RDGetWebMonth(f1[1],&lok);
if(ok) {
time=RDGetWebTime(f0[2]+" "+f0[3],&lok);
if(lok) {
year=f1[2].toInt(&lok);
if(lok&&(year>0)) {
day=f1[0].toInt(&lok);
if(lok&&(day>0)&&(day<=31)) {
ret=QDateTime(QDate(year+2000,month,day),time);
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
}
break;
case 5: // ANSI C asctime() Style
month=RDGetWebMonth(f0[1],&lok);
if(lok) {
time=RDGetWebTime(f0[3]+" GMT",&lok);
if(lok) {
year=f0[4].toInt(&lok);
if(lok&&(year>0)) {
day=f0[2].toInt(&lok);
if(lok&&(day>0)&&(day<=31)) {
ret=QDateTime(QDate(year,month,day),time);
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
break;
case 6: // RFC 822/1123 Style
month=RDGetWebMonth(f0[2],&lok);
if(lok) {
time=RDGetWebTime(f0[4]+" "+f0[5],&lok);
if(lok) {
year=f0[3].toInt(&lok);
if(lok&&(year>0)) {
day=f0[1].toInt(&lok);
if(lok&&(day>0)&&(day<=31)) {
ret=QDateTime(QDate(year,month,day),time);
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
break;
}
return ret;
}
QDate RDGetWebDate(const QString &str,bool *ok)
{
QDate ret;
ret=QDate::fromString(str,Qt::ISODate);
if(ok!=NULL) {
*ok=ret.isValid();
}
return ret;
}
QTime RDGetWebTime(const QString &str,bool *ok)
{
QTime ret;
QStringList f0;
QStringList f1;
QStringList f2;
bool lok=false;
int tz=0;
QTime time;
QTime tztime;
if(ok!=NULL) {
*ok=false;
}
f0=str.trimmed().split(" ");
switch(f0.size()) {
case 1: // XML xs:time Style
if(f0[0].right(1).lower()=="z") { // GMT
tz=RDTimeZoneOffset();
f0[0]=f0[0].left(f0[0].length()-1);
f2=f0[0].split(":");
}
else {
f1=f0[0].split("+");
if(f1.size()==2) { // GMT+
f2=f1[1].split(":");
if(f2.size()==2) {
tztime=QTime(f2[0].toInt(),f2[1].toInt(),0);
if(tztime.isValid()) {
tz=RDTimeZoneOffset()+QTime(0,0,0).secsTo(tztime);
}
}
}
else {
f1=f0[0].split("-");
if(f1.size()==2) { // GMT-
f2=f1[1].split(":");
if(f2.size()==2) {
tztime=QTime(f2[0].toInt(),f2[1].toInt(),0);
if(tztime.isValid()) {
tz=RDTimeZoneOffset()-QTime(0,0,0).secsTo(tztime);
}
}
}
}
f2=f1[0].split(":");
}
if(f2.size()==3) {
time=QTime(f2[0].toInt(),f2[1].toInt(),f2[2].toInt());
if(time.isValid()) {
ret=time.addSecs(tz);
if(ok!=NULL) {
*ok=true;
}
}
}
break;
case 2: // RFC Style
if(f0[1].lower()=="gmt") {
f0=f0[0].split(":");
if(f0.size()==3) {
int hour=f0[0].toInt(&lok);
if(lok) {
int min=f0[1].toInt(&lok);
if(lok) {
int sec=f0[2].toInt(&lok);
if(lok) {
if((hour>=0)&&(hour<=23)&&(min>=0)&&(min<=59)&&(sec>=0)&&
(sec<=60)) {
ret=RDUtcToLocal(QTime(f0[0].toInt(),f0[1].toInt(),
f0[2].toInt()));
if(ok!=NULL) {
*ok=true;
}
}
}
}
}
}
}
break;
}
return ret;
}
int RDGetWebMonth(const QString &str,bool *ok)
{
int ret=0;
if(str.lower()=="jan") {
ret=1;
}
if(str.lower()=="feb") {
ret=2;
}
if(str.lower()=="mar") {
ret=3;
}
if(str.lower()=="apr") {
ret=4;
}
if(str.lower()=="may") {
ret=5;
}
if(str.lower()=="jun") {
ret=6;
}
if(str.lower()=="jul") {
ret=7;
}
if(str.lower()=="aug") {
ret=8;
}
if(str.lower()=="sep") {
ret=9;
}
if(str.lower()=="oct") {
ret=10;
}
if(str.lower()=="nov") {
ret=11;
}
if(str.lower()=="dec") {
ret=12;
}
if(ok!=NULL) {
*ok=ret!=0;
}
return ret;
}

View File

@@ -82,10 +82,6 @@ extern QString RDXmlField(const QString &tag,const QDate &value,
extern QString RDXmlField(const QString &tag,const QTime &value,
const QString &attrs="");
extern QString RDXmlField(const QString &tag);
extern QString RDXmlDate(const QDate &date);
extern QString RDXmlTime(const QTime &time);
extern QString RDXmlDateTime(const QDateTime &datetime);
extern QString RDXmlTimeZoneSuffix();
extern QString RDXmlEscape(const QString &str);
extern QString RDXmlUnescape(const QString &str);
extern QString RDJsonPadding(int padding);
@@ -101,14 +97,8 @@ extern QString RDJsonField(const QString &name,const QString &value,
int padding=0,bool final=false);
extern QString RDJsonField(const QString &name,const QDateTime &value,
int padding=0,bool final=false);
extern QString RDUrlEscape(const QString &str);
extern QString RDUrlUnescape(const QString &str);
extern QString RDWebDateTime(const QDateTime &datetime);
extern QDateTime RDGetWebDateTime(const QString &str,bool *ok=NULL);
extern QDate RDGetWebDate(const QString &str,bool *ok=NULL);
extern QTime RDGetWebTime(const QString &str,bool *ok=NULL);
extern int RDGetWebMonth(const QString &str,bool *ok=NULL);
#endif // RDWEB_H