(1)
(2) 此图说明不必学习 utc 时间,学习本地时间就够,也便于测试 :
(3)
(4)
++
(5)
++ 测试举例:
(6)给出源代码,来自于头文件 qdatetime . h :
/*
UTC是时间标准,确保全球时间同步。
Epoch是基于UTC的时间起点,为计算机系统提供统一的时间计算基准。
二者结合使得时间戳成为跨平台、跨时区的通用时间表示方法,广泛应用于编程、网络通信、安全等领域。
在计算机科学中,Epoch通常指一个固定的时间起点,最经典的例子是Unix时间戳的Epoch:
定义:Unix时间戳的Epoch定义为1970年1月1日00:00:00 UTC,之后的每一秒用一个整数表示。
最经典的是Unix时间戳的Epoch,即1970年1月1日00:00:00 UTC。
作用:作为时间计算的参考点,所有时间戳均基于此点计算经过的秒数(或毫秒数)。
总之, utc 是有用的时间参考系,其及时起点就是 epoch,对应于时间 1970年1月1日00:00:00 UTC
*/
/*
The QDateTime class provides date and time functions.
QDateTime 对象编码日历日期和时钟时间(一个“datetime”)。它结合了 QDate 和QTime类的功能。
它可以从系统时钟读取当前 datetime。它提供了比较 datetimes 和通过添加秒数、天数、月数或年数
来操作 datetime 的函数。
QDateTime可以与QTimeZone类一起描述相对于本地时间、UTC、相对于UTC的指定偏移量或特定时区的日期和时间。
例如,“Europe/Berlin”时区将应用德国使用的夏令时规则。
相比之下,相对于UTC的+3600秒的偏移量比UTC早一小时(通常以ISO标准表示为“UTC+01:00”),
没有夏令时偏移或变化。
在使用本地时间或特定时区时,会考虑时区的转换,例如夏令时的开始和结束(DST;但请参见下文)。
用于表示日期时间系统的选择称为其“timespec”。
通常,可以通过在构造函数中显式提供日期和时间,
或者使用静态函数(如currentDateTime()或fromMSecsSinceEpoch())来创建一个QDateTime对象。
可以通过setDate()和setTime(来更改日期和时间。
还可以使用setMSecsSinceEpoch()函数来设置日期和时间,该函数接受自1970年1月1日00:00:00的毫秒数。
从String()函数返回一个QDateTime,给定一个字符串和一个用于解释字符串中日期的日期格式。
QDateTime::currentDateTime ()返回一个 QDateTime,它表示相对于本地时间的当前时间。
QDateTime::currentDateTimeUtc()返回一个 QDateTime, 表示相对于UTC的当前时间。
date()和time()函数提供对 datetime中的日期和时间的访问。toString()函数以文本格式提供相同的信息。
QDateTime提供了一整套运算符来比较两个QDateTime对象,其中较小的表示较早,较大的表示较晚.
您可以使用addMSecs()函数将datetime增加(或减少)给定数量的毫秒,
使用addSecs函数将datetime增加或减少给定数量的秒,
使用addDays()函数将datetime增加或减少给定的天数。
同样,您可以使用addMonths()和addYears()函数。
daysTo()函数返两个datetime之间的天数,secsTo()函数返回两个datetime之间的秒数,
msecsTo()函数返回两个datetime之间的毫秒数。这些操作在适用的情况下考虑到夏令时和其他时区转换.
使用 toTimeSpec() 以本地时间或UTC表示一个日期时间,
使用 to0ffsetFromUtc() 以UTC的偏移量表示,
或使用toTimeZone() 以一般时区表示。
您可以使用 timeSpec() 来查找QDateTime对象存储其时间相对于的 timeSpec。
当该值为 Qt:TimeZone时,您可以使用timeZone()、来查找它正在使用的时区。
意思是先 timeSpec,后时区 timeZone。
//enum Qt::TimeSpec { LocalTime, UTC, OffsetFromUTC, TimeZone };
注:QDateTime不考虑闰秒。
Note: All conversion to and from string formats is done using the C locale.
注:格里高利历中没有公元0年。该年的日期被认为无效
。公元-1年是“公元前1年或“公历前1年”。公元1年1月1日的前一天是公元前31年12月31日。
Range of Valid Dates:
QDateTime可以表示的值范围取决于内部存储实现。
QDateTime目前以gint64的形式存储,作为表示日期和时间的序列msecs值。
这限制了日期范围约为士2.92亿年而QDate的范围为士20亿年。
在创建具有极端值的QDateTime时,必须小心,以免溢出存储。
支持的值的确切范围因Ot::Timespec和时区而异。
Use of Timezones:
QDateTime 使用系统的时区信息来确定当前本地时区及其相对于UTC的偏移量。
如果系统配置不正确或未更新,QDateTime将给出错误的结果。
QDateTime 同样使用系统提供的信息来确定其他时区相对于 UTC的偏移量。
如果这些信息不完整或过时,QDateTime 将会给出错误的结果。请参阅 QTimeZone 文档以获取更多信息。
在现代的Unix系统中,这意味着QDateTime通常具有关于历史转换(包括DST见下文)的准确信息,只要有可能。
在Windows上,系统不支持历史时区数据,因此历史准确性在时区转换方面没有得到维护,特别是包括DST。
Daylight-Saving Time (DST):
QDateTime 考虑了标准时间和夏令时之间的转换。
例如,如果转换发生在凌晨2点,时钟向前跳到3点,
那么从02:00:00到02:59:59.999之间就有一个“缺失”小时,QDateTime认为这个小时是无效的。
执行的任何日期运算都会考虑到这个缺失小时并返回有效结果。例如,将1分钟加到01:59:59将得到03:00:00。
对干系统时间 time_t可以表示的日期和时间
(在32位时间t的系统上为1901-12-14到2038-01-18:如果类型为64位,则ODateTime可以表示整个范围),
使用标准系统API来确定本地时间相对于UTC的偏移量。
对于这些系统API未处理的日期和时间,使用0TimeZone::svstemTimeZone()函数。
无论哪种情况,使用的偏移信息都取决于系统,并且可能不完整,
或者对于过去的日期,历史上可能不准确。
在任何情况下,对于未来的日期,本地时区的偏移量和夏令时规则在该日期到来之前可能会发生变化。
Offsets From UTC:
对于从UTC开始的偏移量,没有明确的尺寸限制,
但当使用使用【+l-】hh:mm格式的toString()和fromString()方法时,会施加一个隐含的限制,
有效地将范围限制在+/-99小时和59分钟以及整分钟。
请注意,目前没有时区的偏移量超出土14小时的范围,所有已知的偏移量都是5分钟的倍数。
*/
class Q_CORE_EXPORT QDateTime
{
private:
bool equals (const QDateTime & other) const;
bool precedes(const QDateTime & other) const;
friend bool operator==(const QDateTime & lhs, const QDateTime & rhs)
{ return lhs.equals(rhs); }
friend bool operator!=(const QDateTime & lhs, const QDateTime & rhs)
{ return !(lhs == rhs); }
friend bool operator< (const QDateTime & lhs, const QDateTime & rhs)
{ return lhs.precedes(rhs); }
friend bool operator<=(const QDateTime & lhs, const QDateTime & rhs)
{ return !(rhs < lhs); }
friend bool operator> (const QDateTime & lhs, const QDateTime & rhs)
{ return rhs.precedes(lhs); }
friend bool operator>=(const QDateTime & lhs, const QDateTime & rhs)
{ return !(lhs < rhs); }
friend Q_CORE_EXPORT QDataStream & operator<<(QDataStream &, const QDateTime &);
friend Q_CORE_EXPORT QDataStream & operator>>(QDataStream &, QDateTime &);
friend Q_CORE_EXPORT QDebug operator<<(QDebug , const QDateTime &);
struct ShortData //短数据
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN //确实是小端法
quintptr status : 8;
#endif
#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
qint64 msecs : 56;
#else
// note: this is only 24 bits on 32-bit systems...
qintptr msecs : sizeof(void *) * 8 - 8;
#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN //这里存在大端小端的颠倒顺序
quintptr status : 8;
#endif
};
friend class QDateTimePrivate; //下面要用
union Data { //无官方注释
enum {
// To be of any use, we need at least 60 years around 1970,
// which is 1,893,456,000,000 ms.
// That requires 41 bits to store, plus the sign bit.
// With the status byte, the minimum size is 50 bits.
//为了有用,我们至少需要在1970年左右存储60年,即1,893,456,000,000毫秒。
//这需要41位来存储,再加上符号位。使用状态字节,最小大小为50位。
CanBeSmall = sizeof(ShortData) * 8 > 50 //可见这是个布尔量 0 或 1
};
Data() noexcept;
Data(Qt::TimeSpec);
//enum Qt::TimeSpec { LocalTime, UTC, OffsetFromUTC, TimeZone };
Data(const Data & other);
Data( Data && other);
Data & operator=(const Data & other);
~Data();
bool isShort() const;
void detach();
const QDateTimePrivate * operator->() const;
QDateTimePrivate * operator->();
QDateTimePrivate * d ; //本类的数据成员
ShortData data; //又一个数据成员
};
Data d; //本 QDateTime类的数据成员
public:
// (1<<63) ms is 292277024.6 (average Gregorian) years, 格里高利历法
//counted from the start of 1970, so Last is floor(1970 + 292277024.6);
//no year 0, so First is floor(1970 - 1 - 292277024.6) //有效年份的取值范围
enum class YearRange : qint32 { First = -292275056, Last = +292278994 };
//Constructs a null datetime.
//A null datetime is invalid, since its date and time are invalid.
QDateTime() noexcept;
//Constructs a datetime with the given date and time,
//using the Time Zone specified by timeZone.
//If date is valid and time is not, the time will be set to 00:00:00.
//If timeZone is invalid then the datetime will be invalid.
QDateTime(QDate date, QTime time, const QTimeZone & timeZone);
//enum Qt::TimeSpec { LocalTime, UTC, OffsetFromUTC, TimeZone };
QDateTime(QDate date, QTime time, Qt::TimeSpec spec = Qt::LocalTime,
int offsetSeconds = 0);
//Constructs a datetime with the given date and time,
//using the time specification defined by spec and offsetSeconds seconds.
//If date is valid and time is not, the time will be set to midnight.
//If the spec is not Qt::OffsetFromUTC then offsetSeconds will be ignored.
//If the spec is Qt::OffsetFromUTC and offsetSeconds is 0 then the
//timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
//If spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
// i.e. the current system time zone.
//To create a Qt::TimeZone datetime use the correct constructor.
QDateTime(const QDateTime & other) noexcept; //copy构造函数
QDateTime( QDateTime && other) noexcept; //移动构造函数
~QDateTime();
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDateTime) //移动赋值运算符函数
/*
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
Class & operator=(Class && other) noexcept { \
swap(other); \
return *this; \
}
*/
QDateTime & operator=(const QDateTime & other) noexcept; //copy赋值运算符函数
void swap(QDateTime & other) noexcept { qSwap(d.d, other.d.d); }
//Returns a QDateTime object containing a
// datetime msecs milliseconds later than the datetime of this object
//(or earlier if msecs is negative).
//If this datetime is invalid, an invalid datetime will be returned.
[[nodiscard]] QDateTime addMSecs (qint64 msecs ) const;
[[nodiscard]] QDateTime addSecs (qint64 secs ) const;
[[nodiscard]] QDateTime addDays (qint64 days ) const;
[[nodiscard]] QDateTime addMonths(int months) const;
[[nodiscard]] QDateTime addYears (int years ) const;
//Returns the current datetime,
//as reported by the system clock, in the local time zone.
static QDateTime currentDateTime ();
//QDateTime(2025-05-08 07:14:53.454 中国标准时间 Qt::LocalTime)
//QDateTime(2025-05-07 23:14:53.469 UTC Qt::UTC) //如此大的差异,不再学习 UTC时间了!!
static QDateTime currentDateTimeUtc();
//Returns the current datetime, as reported by the system clock, in UTC.
static qint64 currentSecsSinceEpoch() noexcept;
static QDateTime fromSecsSinceEpoch(qint64 secs,
Qt::TimeSpec spec = Qt::LocalTime,
int offsetFromUtc = 0);
static QDateTime fromSecsSinceEpoch(qint64 secs,
const QTimeZone & timeZone);
static qint64 currentMSecsSinceEpoch() noexcept;
static QDateTime fromMSecsSinceEpoch(qint64 msecs,
Qt::TimeSpec spec = Qt::LocalTime,
int offsetFromUtc = 0);
static QDateTime fromMSecsSinceEpoch(qint64 msecs,
const QTimeZone & timeZone);
//enum Qt::TimeSpec { LocalTime, UTC, OffsetFromUTC, TimeZone };
QDateTime toTimeSpec ( Qt::TimeSpec spec) const;
//Returns a datetime containing the date and time information in this datetime,
//but specified using the Qt::LocalTime definition.
inline QDateTime toLocalTime () const
{ return toTimeSpec(Qt::LocalTime); }
inline QDateTime toUTC () const
{ return toTimeSpec(Qt::UTC); }
//Returns a datetime containing the date and time information in this datetime,
//but specified using the Qt::UTC definition.
QDateTime toOffsetFromUtc( int offsetSeconds) const;
QDateTime toTimeZone (const QTimeZone & toZone ) const;
bool isNull () const;
bool isValid () const;
bool isDaylightTime() const;
//Returns if this datetime falls in Daylight-Saving Time.
//If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will
//always return false.
//返回从当前日期时间到另一个日期时间的天数。
//天数计算为从当前日期时间到另一个日期时间之间午夜到达的次数。
//这意味着从23:55到第二天0:05的10分钟差异算作一天。
//如果另一个日期时间早于此日期时间,则返回的值为负数。
qint64 daysTo(const QDateTime &) const;
qint64 secsTo(const QDateTime &) const;
qint64 msecsTo(const QDateTime &) const;
//返回从当前日期时间到另一个日期时间的毫秒数。如果另一个日期时间早于当前日期时间,则返回的值为负。
//在进行比较之前,将两个日期时间转换为 Qt::UTC,
//以确保如果两个日期时间中的一个适用夏令时(DST)而另一个不适用,则结果正确。
//如果任一日期时间无效,则返回 0。
QDate date() const; //Returns the date part of the datetime.
void setDate(QDate date);
//若时间值之前为 null则改为零时间值,否则此处会维持时间部分不变,即只改变日期。
//Sets the date part of this datetime to date.
//If no time is set yet, it is set to midnight.
//If date is invalid, this QDateTime becomes invalid.
QTime time() const; //Returns the time part of the datetime.
void setTime(QTime time);
//Sets the time part of this datetime to time.
//If time is not valid, this function sets it to midnight.
//Therefore, it's possible to clear any set time in a QDateTime by setting
//it to a default QTime:
QTimeZone timeZone() const;
void setTimeZone(const QTimeZone & toZone);
QString timeZoneAbbreviation() const;
//enum Qt::TimeSpec { LocalTime, UTC, OffsetFromUTC, TimeZone };
Qt::TimeSpec timeSpec() const;
void setTimeSpec(Qt::TimeSpec spec);
int offsetFromUtc() const; //utc 见20,是优秀的时间,但中国用 CST时间
void setOffsetFromUtc(int offsetSeconds);
qint64 toSecsSinceEpoch() const; //新纪元 Epoch
void setSecsSinceEpoch(qint64 secs);
qint64 toMSecsSinceEpoch() const;
void setMSecsSinceEpoch(qint64 msecs);
//enum Qt::DateFormat { TextDate, ISODate, RFC2822Date = 8, ISODateWithMs };
QString toString( Qt::DateFormat format = Qt::TextDate) const;
QString toString( QStringView format, QCalendar cal = QCalendar()) const;
QString toString(const QString & format, QCalendar cal = QCalendar()) const
{ return toString(qToStringViewIgnoringNull(format), cal); }
static QDateTime fromString(const QString & string,
const QString & format, //默认公历
QCalendar cal = QCalendar())
{ return fromString(string, qToStringViewIgnoringNull(format), cal); }
static QDateTime fromString(const QString & string,
QStringView format,
QCalendar cal = QCalendar());
static QDateTime fromString(const QString & string,
Qt::DateFormat format = Qt::TextDate)
{ return fromString(qToStringViewIgnoringNull(string), format); }
static QDateTime fromString( QStringView string,
Qt::DateFormat format = Qt::TextDate);
static QDateTime fromString( QStringView string,
QStringView format,
QCalendar cal = QCalendar())
{ return fromString(string.toString(), format, cal); }
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QDateTime fromCFDate( CFDateRef date);
CFDateRef toCFDate() const Q_DECL_CF_RETURNS_RETAINED;
NSDate * toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED;
static QDateTime fromNSDate(const NSDate * date);
#endif
}; //完结 class QDateTime
Q_DECLARE_SHARED(QDateTime)
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream & operator<<(QDataStream &, QDate );
Q_CORE_EXPORT QDataStream & operator>>(QDataStream &, QDate &);
Q_CORE_EXPORT QDataStream & operator<<(QDataStream &, QTime );
Q_CORE_EXPORT QDataStream & operator>>(QDataStream &, QTime &);
Q_CORE_EXPORT QDataStream & operator<<(QDataStream &, const QDateTime &);
Q_CORE_EXPORT QDataStream & operator>>(QDataStream &, QDateTime &);
#endif // QT_NO_DATASTREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, QDate );
Q_CORE_EXPORT QDebug operator<<(QDebug, QTime );
Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
// QDateTime is not noexcept for now --
// to be revised once timezone and calendaring support is added
//QDateTime 目前不是 noexcept--一旦添加了时区和日历支持,将对其进行修订。
Q_CORE_EXPORT size_t qHash(const QDateTime & key, size_t seed = 0);
Q_CORE_EXPORT size_t qHash( QDate key, size_t seed = 0) noexcept;
Q_CORE_EXPORT size_t qHash( QTime key, size_t seed = 0) noexcept;
(7)
谢谢