⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timezone.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "timezone.h"#include <qfile.h>#include <qfileinfo.h>#include <qcstring.h>#include <qdatastream.h>#include <qasciidict.h>#include <qcstring.h>#include <qdatetime.h>#include <qarray.h>#include <qmap.h>#include <qdir.h>#include <qregexp.h>#include <stdlib.h>#include <time.h>#include "qtopia/qpeapplication.h"#include "qtopia/config.h"#ifdef QTOPIA_DESKTOP#include <qdconfig.h>#endif/******************************************************************* * * TimeZonePrivate * *******************************************************************/class TimeZonePrivate{public:    TimeZonePrivate( QCString idLocation ) : id(idLocation)	{	}    QCString id;    static QCString zonePath();    static QCString zoneFile();    static QDateTime setUtcTime( long t ){    QDateTime r;    time_t tmpTime = t;    tm *tM = gmtime( &tmpTime );    if (tM){	r.setDate( QDate( tM->tm_year + 1900, tM->tm_mon + 1, tM->tm_mday ) );	r.setTime( QTime( tM->tm_hour, tM->tm_min, tM->tm_sec ) );    }else{	r.setDate(QDate(1970, 1, 1));	r.setTime(QTime(0,0,0));    }    return r;}    static uint toTime_t( const QDateTime &utc )	{	    QTime t = utc.time();	    QDate d = utc.date();	    tm brokenDown;	    brokenDown.tm_sec = t.second();	    brokenDown.tm_min = t.minute();	    brokenDown.tm_hour = t.hour();	    brokenDown.tm_mday = d.day();	    brokenDown.tm_mon = d.month() - 1;	    brokenDown.tm_year = d.year() - 1900;	    brokenDown.tm_isdst = -1;	    QCString origTz = getenv( "TZ" );	    setenv( "TZ", "GMT", TRUE );	    tzset();	    int secsSince1Jan1970UTC = (int) mktime( &brokenDown );	    if ( !origTz.isEmpty() )	        setenv( "TZ", origTz, TRUE );	    if ( secsSince1Jan1970UTC < -1 )		secsSince1Jan1970UTC = -1;	    return (uint) secsSince1Jan1970UTC;	}private:    static QCString sZonePath;    static QCString sZoneFile;};QCString TimeZonePrivate::sZonePath(0);QCString TimeZonePrivate::zonePath(){    if ( sZonePath.isNull() ) {#if defined(Q_OS_WIN32)	sZonePath = QPEApplication::qpeDir() + "etc\\zoneinfo\\";#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)	sZonePath = "/usr/share/zoneinfo/";#else	sZonePath = QPEApplication::qpeDir() + "etc/zoneinfo/";#endif    }    return sZonePath;}QCString TimeZonePrivate::sZoneFile(0);QCString TimeZonePrivate::zoneFile(){    if ( sZoneFile.isNull() ) {	sZoneFile = zonePath() + "zone.tab";    }    return sZoneFile;}/******************************************************************* * * TimeZoneData * *******************************************************************/class TimeZoneData{public:    TimeZoneData() : mId(0) { }    TimeZoneData( const QCString &id );    bool match( const QDateTime &t,	long utcOffset, bool dst,	QCString standardAbbrev,	QCString daylightAbbrev ) const;    bool isValid() const;    bool isDaylightSavings( const QDateTime & ) const;    QDateTime toUtc( const QDateTime & ) const;    QDateTime fromUtc( const QDateTime & ) const;    QDateTime convert( const QDateTime &, const TimeZoneData & ) const;    QCString id() const { return mId; }    QCString standardAbbreviation() const;    QCString dstAbbreviation() const;    /* for debugging purposes */    void dump() const;    static TimeZoneData *null;private:    /** find the transition time that should apply to \a t    */    int findTranstionTimeIndex( const QDateTime & t, bool utc ) const;    int findTimeTypeIndex( const QDateTime & t, bool utc ) const;    QCString mId;    bool mDstRule;    struct transitionInfo {	QDateTime time;	int timeTypeIndex;    };    struct ttinfo {	long          utcOffset; // in secs	bool           isDst;	unsigned int  abbreviationIndex;	bool          isWallTime;	bool          isTransitionLocal;    };    QArray<transitionInfo> transitionTimes;    QArray<ttinfo> timeTypes;    QMap<uint, QCString> abbreviations;};TimeZoneData *TimeZoneData::null = new TimeZoneData();bool TimeZoneData::match( const QDateTime &c,			  long utcOffset, bool hasDst,			  QCString standardAbbrev,			  QCString daylightAbbrev ) const{    if ( !isValid() )	return FALSE;    ttinfo transInfo = timeTypes[ findTimeTypeIndex( c, FALSE ) ];    utcOffset *= -1;    if ( (utcOffset == transInfo.utcOffset) && (hasDst == mDstRule) ) {	// if not given abbreviation string to match, then matching	// on offset is the best we can do	if ( standardAbbrev.isEmpty() )	    return TRUE;	if ( hasDst )	    return ( daylightAbbrev == abbreviations[ transInfo.abbreviationIndex ] );	return ( standardAbbrev == abbreviations[ transInfo.abbreviationIndex ] );    }    return FALSE;}bool TimeZoneData::isValid() const{    return (transitionTimes.count() > 0) || (timeTypes.count() > 0);}int TimeZoneData::findTranstionTimeIndex( const QDateTime & c, bool utc ) const{    for ( int i = 0; i < (int)transitionTimes.count(); ++i ) {	transitionInfo transTime = transitionTimes[i];	ttinfo transInfo = timeTypes[ transTime.timeTypeIndex ];	QDateTime thisItTime = transTime.time;	// if comparing with utc, then shift the it time to utc	if ( !utc )	    thisItTime = thisItTime.addSecs( transInfo.utcOffset );	if ( thisItTime > c ) {	    // gone one too far; we've passed it. return the previous one, if	    // it exists	    if ( i > 0 )		return i-1;	    return i;	}    }    // must be the last index    return transitionTimes.count()-1;}int TimeZoneData::findTimeTypeIndex( const QDateTime & c, bool utc ) const{    int transIndex = findTranstionTimeIndex( c, utc );    if ( transIndex < 0 )	return 0;    return transitionTimes[ transIndex ].timeTypeIndex;}QCString TimeZoneData::standardAbbreviation() const{    QDateTime dt = QDateTime::currentDateTime();    int transIndex = findTranstionTimeIndex( dt, FALSE );    while ( transIndex >= 0 ) {	int timeIndex = transitionTimes[ transIndex ].timeTypeIndex;	if ( !timeTypes[ timeIndex ].isDst )	    return abbreviations[ timeTypes[ timeIndex ].abbreviationIndex ];	transIndex--;    }    return "";}QCString TimeZoneData::dstAbbreviation() const{    QDateTime dt = QDateTime::currentDateTime();    int transIndex = findTranstionTimeIndex( dt, FALSE );    while ( transIndex >= 0 ) {	int timeIndex = transitionTimes[ transIndex ].timeTypeIndex;	if ( timeTypes[ timeIndex ].isDst )	    return abbreviations[ timeTypes[ timeIndex ].abbreviationIndex ];	transIndex--;    }    return "";}bool TimeZoneData::isDaylightSavings( const QDateTime & c ) const{    int timeIndex = findTimeTypeIndex( c, FALSE );    return timeTypes[ timeIndex ].isDst;}QDateTime TimeZoneData::toUtc( const QDateTime &thisT ) const{    if ( !isValid() ) { qWarning("TimeZoneData::toUtc invalid"); return QDateTime(); }    // find the appropriate utc time    int timeIndex = findTimeTypeIndex( thisT, FALSE );    return thisT.addSecs( -1 * timeTypes[ timeIndex ].utcOffset );}QDateTime TimeZoneData::fromUtc( const QDateTime &utc ) const{    if ( !isValid() ) { qWarning("TimeZoneData::fromUtc invalid"); return QDateTime(); }    // convert from utc to "this" timezone    int timeIndex = findTimeTypeIndex( utc, TRUE );    return utc.addSecs( timeTypes[ timeIndex ].utcOffset );}QDateTime TimeZoneData::convert( const QDateTime &,				 const TimeZoneData & ) const{    if ( !isValid() ) { qWarning("TimeZoneData::convert invalid"); return QDateTime(); }    qWarning("TimeZoneData::convert not implemented yet");    return QDateTime();}TimeZoneData::TimeZoneData( const QCString & loc ) : mId( loc ), mDstRule( FALSE ){    long numUtcIndicators, numStandardIndicators, numLeapSecs,	numTransitionTimes, numTimeTypes, tzAbbreviationChars;    QString fname = TimeZonePrivate::zonePath() + mId;    fname = QDir::convertSeparators( fname );    QFile f( fname );    //qDebug(" fname %s exists %d", fname.data(), QFile::exists( fname ) );    if ( !f.open( IO_ReadOnly ) ) {	qDebug("Unable to open '%s'", fname.latin1() );	//qDebug("\texists %d", QFile::exists( fname ));	//exit(1);	return;    }    QByteArray data = f.readAll();    f.close();    //qDebug("data size = %d; value='%s'", data.size(),data.data());    if ( !data.size() ) {	qDebug("invalid data size = %d", data.size());	return;    }    QDataStream ds( data, IO_ReadOnly );    char rawMagic[5];    uint nbytes=4;    rawMagic[4] = 0;    ds.readRawBytes( rawMagic, nbytes );    QCString magic( rawMagic, nbytes+1 );    if ( magic != "TZif"#ifdef Q_OS_MAC	&& ( magic[0] || magic[1] || magic[2] || magic[3] )#endif    ) {	//qDebug("magic match failed: '%s'",rawMagic);	return;    }    char reserved[16];    nbytes = 16;    ds.readRawBytes(reserved, nbytes);    if ( nbytes != 16 ) {	qDebug("reserved size failed");	return;    }    ds >> numUtcIndicators >> numStandardIndicators >> numLeapSecs       >> numTransitionTimes >> numTimeTypes >> tzAbbreviationChars;    transitionInfo transInfo;    transitionTimes.resize( numTransitionTimes );    int i =0;    for ( i = 0; i < numTransitionTimes; ++i ) {	long secs;	ds >> secs;	transInfo.time = TimeZonePrivate::setUtcTime( secs );	if (transInfo.time.isNull()){	    qWarning("Invalid transistion time for %s", id().data());	}	transInfo.timeTypeIndex = 0;	transitionTimes[i] = transInfo;    }    unsigned char byte = 0;    for ( i = 0; i < numTransitionTimes; ++i ) {	ds >> byte;	transInfo = transitionTimes[i];	transInfo.timeTypeIndex = (int) byte;	transitionTimes[i] = transInfo;    }    timeTypes.resize( numTimeTypes );    unsigned int maxAbbrevIndex = 0;    ttinfo offsetInfo;    for ( i =0; i < numTimeTypes; ++i ) {	ds >> offsetInfo.utcOffset;	ds >> byte;	offsetInfo.isDst = (bool) byte;	if ( offsetInfo.isDst )	    mDstRule = TRUE;	ds >> byte;	offsetInfo.abbreviationIndex = (unsigned int)byte;	timeTypes[i] = offsetInfo;	if (  offsetInfo.abbreviationIndex > maxAbbrevIndex )	    maxAbbrevIndex = offsetInfo.abbreviationIndex;    }    char abbrev[5];    abbrev[4] = 0;    nbytes = 4;    for ( uint index = 0; index <= maxAbbrevIndex; index += 4 ) {	ds.readRawBytes( abbrev, nbytes );	abbreviations.insert( index, abbrev );    }    // leap seconds aren't set for any file, so not exactly sure    // what they are used for    for ( i = 0; i < numLeapSecs; ++i ) {	long leapSecOccurs, applyLeapSecs;	ds >> leapSecOccurs >> applyLeapSecs;    }    for ( i = 0; i < numStandardIndicators; ++i ) {	ds >> byte;	offsetInfo = timeTypes[i];	offsetInfo.isWallTime = !(bool) byte;	timeTypes[i] = offsetInfo;    }    for ( i = 0; i < numUtcIndicators; ++i ) {	ds >> byte;	offsetInfo = timeTypes[i];	offsetInfo.isTransitionLocal = !(bool) byte;	timeTypes[i] = offsetInfo;    }}void TimeZoneData::dump() const{    if ( !isValid() ) {	qDebug("Loading failed!");	//return;    }    qDebug("TimeZoneData::dump() for %s", (TimeZonePrivate::zonePath() + id()).data());    qDebug("numTransitionTimes %d numTimeTypes %d",	   transitionTimes.count(), timeTypes.count() );    int i;    for ( i = 0; i < (int) transitionTimes.count(); ++i )	qDebug(" transitionTimes[%d] = %s\t\ttimeTypeIndex %d", i, transitionTimes[i].time.toString().latin1(), transitionTimes[i].timeTypeIndex );    for ( i = 0; i < (int) timeTypes.count(); ++i ) {	ttinfo offsetInfo = timeTypes[i];	qDebug("time type[%d] => offset: %ld isdst %d abbrev timeTypeIndex: %d abbrev %s isWall %d isTransitionLocal %d",	       i, offsetInfo.utcOffset/(60*60), offsetInfo.isDst, offsetInfo.abbreviationIndex, (const char *)abbreviations[offsetInfo.abbreviationIndex],	       (int) offsetInfo.isWallTime, (int) offsetInfo.isTransitionLocal );    }    qDebug("TimeZoneData::dump() for %s", (TimeZonePrivate::zonePath() + id()).data());}/******************************************************************* * * TimeZoneLocation * *******************************************************************/class TimeZoneLocation{public:    TimeZoneLocation( const char *line );    bool isValid() const { return mCity != NULL; }// in seconds    int lat() const;// in seconds    int lon() const;    QCString latStr() const;    QCString lonStr() const;    QString description() const;    QString area() const;    QString city() const;    QCString countryCode() const;    QCString id() const;    int distance( const TimeZoneLocation &e ) const	{ return lat() - e.lat() + lon() - e.lon(); }    void dump() const;    static void load( QAsciiDict< TimeZoneLocation > &store );    static QStringList languageList();private:    QCString mLine;    const char * mArea;    const char * mCity;    const char * mDescription;    const char *mCountryCode;    QString mLatStr;    QString mLonStr;    QCString mId;};TimeZoneLocation::TimeZoneLocation( const char *line )    : mLine( line ), mArea( NULL ), mCity( NULL ), mDescription( NULL ){    char *pos = mLine.data();    char *endPos = pos + mLine.length();    char *tokenBegin = pos;    int tokenNum = 0;    while( pos < endPos ) {	if ( *pos == '\t' || *pos == '\n'	     || *pos == '\r' || pos+1 == endPos ) {	    *pos = '\0';	    switch ( tokenNum ) {	    case 0:		mCountryCode = tokenBegin;		break;	    case 1: {		QString latLonStr( tokenBegin );		if ( latLonStr.length() == 15 ) {		    mLatStr = latLonStr.mid(0, 7);		    mLonStr = latLonStr.mid(7);		} else if ( latLonStr.length() == 11 ) {		    mLatStr = latLonStr.mid(0, 5);		    mLonStr = latLonStr.mid(5);		}		else {		    qWarning("can't parse lat lon str %s", latLonStr.latin1() );		    return;		}		// sanity check		if ( mLatStr[0] != '+' && mLatStr[0] != '-') {		    qWarning("lat/lon is invalid");		    return;		}	    }		break;	    case 2: {		mArea = tokenBegin;		// the string after the last slash is the city		// also, convert the _ to ' ' in the area strings		char *areaPos = pos-1;		for ( ;areaPos > mArea && *areaPos != '/'; --areaPos ) ;		*areaPos = '\0';		mCity = areaPos+1;	    } break;	    case 3:		mDescription = tokenBegin;		break;	    }//	    if ( debug )	    //	qDebug("\ttoken %d = =%s=", tokenNum, tokenBegin);	    tokenNum++;	    tokenBegin = pos+1;	}	pos++;    }    mId  = QCString(mArea) + '/' + QCString(mCity);}int TimeZoneLocation::lat() const{    int deg, min, sec;    int sign = 1;    if ( mLatStr[0] == '-' )	sign = -1;    deg = mLatStr.mid(1, 2).toInt();    min = mLatStr.mid(3, 2).toInt();    sec = 0;    if ( mLatStr.length() == 7 )	sec = mLatStr.mid(5, 2).toInt();    return sign*deg*3600 + sign*min*60 + sign*sec;}int TimeZoneLocation::lon() const{    int deg, min, sec;    int sign = 1;    if ( mLonStr[0] == '-' )	sign = -1;    deg = mLonStr.mid(1, 3).toInt();    min = mLonStr.mid( 4, 2 ).toInt();    sec = 0;    if ( mLonStr.length() == 8 )	sec = mLonStr.mid( 6, 2 ).toInt();    return sign*deg*3600 + sign*min*60 + sign*sec;}QCString TimeZoneLocation::latStr() const{    return mLatStr.latin1();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -