00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexidatetimeformatter.h"
00021
00022 #include <kdebug.h>
00023 #include <klocale.h>
00024 #include <kglobal.h>
00025 #include <kdatepicker.h>
00026 #include <kdatetbl.h>
00027 #include <klineedit.h>
00028 #include <kpopupmenu.h>
00029 #include <kdatewidget.h>
00030
00031 KexiDateFormatter::KexiDateFormatter()
00032 {
00033
00035 QString df( KGlobal::locale()->dateFormatShort() );
00036 if (df.length()>2)
00037 m_separator = df.mid(2,1);
00038 else
00039 m_separator = "-";
00040 const int separatorLen = m_separator.length();
00041 QString yearMask("9999");
00042 QString yearDateFormat("yyyy"),
00043 monthDateFormat("MM"),
00044 dayDateFormat("dd");
00045 bool ok = df.length()>=8;
00046 int yearpos, monthpos, daypos;
00047 if (ok) {
00050 yearpos = df.find("%y", 0, false);
00051 m_longYear = !(yearpos>=0 && df.mid(yearpos+1, 1)=="y");
00052 if (!m_longYear) {
00053 yearMask = "99";
00054 yearDateFormat = "yy";
00055 }
00056 monthpos = df.find("%m", 0, true);
00057 m_monthWithLeadingZero = true;
00058 if (monthpos<0) {
00059 monthpos = df.find("%n", 0, false);
00060 m_monthWithLeadingZero = false;
00061 monthDateFormat = "M";
00062 }
00063 daypos = df.find("%d", 0, true);
00064 m_dayWithLeadingZero = true;
00065 if (daypos<0) {
00066 daypos = df.find("%e", 0, false);
00067 m_dayWithLeadingZero = false;
00068 dayDateFormat = "d";
00069 }
00070 ok = (yearpos>=0 && monthpos>=0 && daypos>=0);
00071 }
00072 m_order = QDateEdit::YMD;
00073 if (ok) {
00074 if (yearpos<monthpos && monthpos<daypos) {
00075
00076 }
00077 else if (yearpos<daypos && daypos<monthpos) {
00078 m_order = QDateEdit::YDM;
00081 m_inputMask = QString("%1%299%399").arg(yearMask).arg(m_separator).arg(m_separator);
00082 m_qtFormat = yearDateFormat+m_separator+dayDateFormat+m_separator+monthDateFormat;
00083 m_yearpos = 0;
00084 m_daypos = yearMask.length()+separatorLen;
00085 m_monthpos = m_daypos+2+separatorLen;
00086 }
00087 else if (daypos<monthpos && monthpos<yearpos) {
00088 m_order = QDateEdit::DMY;
00089 m_inputMask = QString("99%199%2%3").arg(m_separator).arg(m_separator).arg(yearMask);
00090 m_qtFormat = dayDateFormat+m_separator+monthDateFormat+m_separator+yearDateFormat;
00091 m_daypos = 0;
00092 m_monthpos = 2+separatorLen;
00093 m_yearpos = m_monthpos+2+separatorLen;
00094 }
00095 else if (monthpos<daypos && daypos<yearpos) {
00096 m_order = QDateEdit::MDY;
00097 m_inputMask = QString("99%199%2%3").arg(m_separator).arg(m_separator).arg(yearMask);
00098 m_qtFormat = monthDateFormat+m_separator+dayDateFormat+m_separator+yearDateFormat;
00099 m_monthpos = 0;
00100 m_daypos = 2+separatorLen;
00101 m_yearpos = m_daypos+2+separatorLen;
00102 }
00103 else
00104 ok = false;
00105 }
00106 if (!ok || m_order == QDateEdit::YMD) {
00107 m_inputMask = QString("%1%299%399").arg(yearMask).arg(m_separator).arg(m_separator);
00108 m_qtFormat = yearDateFormat+m_separator+monthDateFormat+m_separator+dayDateFormat;
00109 m_yearpos = 0;
00110 m_monthpos = yearMask.length()+separatorLen;
00111 m_daypos = m_monthpos+2+separatorLen;
00112 }
00113 m_inputMask += ";_";
00114 }
00115
00116 KexiDateFormatter::~KexiDateFormatter()
00117 {
00118 }
00119
00120 QDate KexiDateFormatter::stringToDate( const QString& str ) const
00121 {
00122 bool ok = true;
00123 int year = str.mid(m_yearpos, m_longYear ? 4 : 2).toInt(&ok);
00124 if (!ok)
00125 return QDate();
00126 if (year < 30) {
00127 year = 2000 + year;
00128 }
00129 else if (year < 100) {
00130 year = 1900 + year;
00131 }
00132
00133 int month = str.mid(m_monthpos, 2).toInt(&ok);
00134 if (!ok)
00135 return QDate();
00136
00137 int day = str.mid(m_daypos, 2).toInt(&ok);
00138 if (!ok)
00139 return QDate();
00140
00141 QDate date(year, month, day);
00142 if (!date.isValid())
00143 return QDate();
00144 return date;
00145 }
00146
00147 QVariant KexiDateFormatter::stringToVariant( const QString& str ) const
00148 {
00149 if (isEmpty(str))
00150 return QVariant();
00151 const QDate date( stringToDate( str ) );
00152 if (date.isValid())
00153 return date;
00154 return QVariant();
00155 }
00156
00157 bool KexiDateFormatter::isEmpty( const QString& str ) const
00158 {
00159 QString s(str);
00160 return s.replace(m_separator,"").stripWhiteSpace().isEmpty();
00161 }
00162
00163 QString KexiDateFormatter::dateToString( const QDate& date ) const
00164 {
00165 return date.toString(m_qtFormat);
00166 }
00167
00168
00169
00170 KexiTimeFormatter::KexiTimeFormatter()
00171 : m_hmsRegExp( new QRegExp("(\\d*):(\\d*):(\\d*).*( am| pm){,1}", false) )
00172 , m_hmRegExp( new QRegExp("(\\d*):(\\d*).*( am| pm){,1}", false) )
00173 {
00174 QString tf( KGlobal::locale()->timeFormat() );
00175
00176 QString hourVariable, minVariable, secVariable;
00177
00178
00179 m_24h = true;
00180 m_hoursWithLeadingZero = true;
00181 m_hourpos = tf.find("%H", 0, true);
00182 if (m_hourpos>=0) {
00183 m_24h = true;
00184 m_hoursWithLeadingZero = true;
00185 }
00186 else {
00187 m_hourpos = tf.find("%k", 0, true);
00188 if (m_hourpos>=0) {
00189 m_24h = true;
00190 m_hoursWithLeadingZero = false;
00191 }
00192 else {
00193 m_hourpos = tf.find("%I", 0, true);
00194 if (m_hourpos>=0) {
00195 m_24h = false;
00196 m_hoursWithLeadingZero = true;
00197 }
00198 else {
00199 m_hourpos = tf.find("%l", 0, true);
00200 if (m_hourpos>=0) {
00201 m_24h = false;
00202 m_hoursWithLeadingZero = false;
00203 }
00204 }
00205 }
00206 }
00207 m_minpos = tf.find("%M", 0, true);
00208 m_secpos = tf.find("%S", 0, true);
00209 m_ampmpos = tf.find("%p", 0, true);
00210
00211 if (m_hourpos<0 || m_minpos<0) {
00212
00213 tf = "%H:%M:%S";
00214 m_24h = true;
00215 m_hoursWithLeadingZero = false;
00216 m_hourpos = 0;
00217 m_minpos = 3;
00218 m_secpos = m_minpos + 3;
00219 m_ampmpos = -1;
00220 }
00221 hourVariable = tf.mid(m_hourpos, 2);
00222
00223 m_inputMask = tf;
00224
00225
00226
00227 m_inputMask.replace( hourVariable, "99" );
00228 m_inputMask.replace( "%M", "99" );
00229 m_inputMask.replace( "%S", "00" );
00230 m_inputMask.replace( "%p", "AA" );
00231 m_inputMask += ";_";
00232
00233 m_outputFormat = tf;
00234 }
00235
00236 KexiTimeFormatter::~KexiTimeFormatter()
00237 {
00238 delete m_hmsRegExp;
00239 delete m_hmRegExp;
00240 }
00241
00242 QTime KexiTimeFormatter::stringToTime( const QString& str ) const
00243 {
00244 int hour, min, sec;
00245 bool pm = false;
00246
00247 bool tryWithoutSeconds = true;
00248 if (m_secpos>=0) {
00249 if (-1 != m_hmsRegExp->search(str)) {
00250 hour = m_hmsRegExp->cap(1).toInt();
00251 min = m_hmsRegExp->cap(2).toInt();
00252 sec = m_hmsRegExp->cap(3).toInt();
00253 if (m_ampmpos >= 0 && m_hmsRegExp->numCaptures()>3)
00254 pm = m_hmsRegExp->cap(4).stripWhiteSpace().lower()=="pm";
00255 tryWithoutSeconds = false;
00256 }
00257 }
00258 if (tryWithoutSeconds) {
00259 if (-1 == m_hmRegExp->search(str))
00260 return QTime(99,0,0);
00261 hour = m_hmRegExp->cap(1).toInt();
00262 min = m_hmRegExp->cap(2).toInt();
00263 sec = 0;
00264 if (m_ampmpos >= 0 && m_hmRegExp->numCaptures()>2)
00265 pm = m_hmsRegExp->cap(4).lower()=="pm";
00266 }
00267
00268 if (pm && hour < 12)
00269 hour += 12;
00270 return QTime(hour, min, sec);
00271 }
00272
00273 QVariant KexiTimeFormatter::stringToVariant( const QString& str )
00274 {
00275 if (isEmpty( str ))
00276 return QVariant();
00277 const QTime time( stringToTime( str ) );
00278 if (time.isValid())
00279 return time;
00280 return QVariant();
00281 }
00282
00283 bool KexiTimeFormatter::isEmpty( const QString& str ) const
00284 {
00285 QString s(str);
00286 return s.replace(':',"").stripWhiteSpace().isEmpty();
00287 }
00288
00289 QString KexiTimeFormatter::timeToString( const QTime& time ) const
00290 {
00291 if (!time.isValid())
00292 return QString::null;
00293
00294 QString s(m_outputFormat);
00295 if (m_24h) {
00296 if (m_hoursWithLeadingZero)
00297 s.replace( "%H", QString::fromLatin1(time.hour()<10 ? "0" : "") + QString::number(time.hour()) );
00298 else
00299 s.replace( "%k", QString::number(time.hour()) );
00300 }
00301 else {
00302 int time12 = (time.hour()>12) ? (time.hour()-12) : time.hour();
00303 if (m_hoursWithLeadingZero)
00304 s.replace( "%I", QString::fromLatin1(time12<10 ? "0" : "") + QString::number(time12) );
00305 else
00306 s.replace( "%l", QString::number(time12) );
00307 }
00308 s.replace( "%M", QString::fromLatin1(time.minute()<10 ? "0" : "") + QString::number(time.minute()) );
00309 if (m_secpos>=0)
00310 s.replace( "%S", QString::fromLatin1(time.second()<10 ? "0" : "") + QString::number(time.second()) );
00311 if (m_ampmpos>=0)
00312 s.replace( "%p", KGlobal::locale()->translate( time.hour()>=12 ? "pm" : "am") );
00313 return s;
00314 }
00315
00316
00317
00318 QString dateTimeInputMask(const KexiDateFormatter& dateFormatter, const KexiTimeFormatter& timeFormatter)
00319 {
00320 QString mask(dateFormatter.inputMask());
00321 mask.truncate(dateFormatter.inputMask().length()-2);
00322 return mask + " " + timeFormatter.inputMask();
00323 }
00324
00325 QDateTime stringToDateTime(
00326 const KexiDateFormatter& dateFormatter, const KexiTimeFormatter& timeFormatter, const QString& str)
00327 {
00328 QString s( str.stripWhiteSpace() );
00329 const int timepos = s.find(" ");
00330 const bool emptyTime = timepos >= 0 && timeFormatter.isEmpty(s.mid(timepos+1));
00331 if (emptyTime)
00332 s = s.left(timepos);
00333 if (timepos>0 && !emptyTime) {
00334 return QDateTime(
00335 dateFormatter.stringToDate( s.left(timepos) ),
00336 timeFormatter.stringToTime( s.mid(timepos+1) )
00337 );
00338 }
00339 else {
00340 return QDateTime(
00341 dateFormatter.stringToDate( s ),
00342 QTime(0,0,0)
00343 );
00344 }
00345 }
00346
00347 bool dateTimeIsEmpty( const KexiDateFormatter& dateFormatter, const KexiTimeFormatter& timeFormatter,
00348 const QString& str )
00349 {
00350 int timepos = str.find(" ");
00351 const bool emptyTime = timepos >= 0 && timeFormatter.isEmpty(str.mid(timepos+1));
00352 return (timepos >= 0 && dateFormatter.isEmpty(str.left(timepos))
00353 && emptyTime);
00354 }
00355
00356 bool dateTimeIsValid( const KexiDateFormatter& dateFormatter,
00357 const KexiTimeFormatter& timeFormatter, const QString& str )
00358 {
00359 int timepos = str.find(" ");
00360 const bool emptyTime = timepos >= 0 && timeFormatter.isEmpty(str.mid(timepos+1));
00361 if (timepos >= 0 && dateFormatter.isEmpty(str.left(timepos))
00362 && emptyTime)
00363
00364 return true;
00365 return timepos>=0 && dateFormatter.stringToDate( str.left(timepos) ).isValid()
00366 && (emptyTime || timeFormatter.stringToTime( str.mid(timepos+1) ).isValid());
00367 }