📄 ptime.cxx
字号:
/*
* ptime.cxx
*
* Time and date classes.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Revision: 19008 $
* $Author: rjongbloed $
* $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
*/
#include <ptlib.h>
#include <ctype.h>
///////////////////////////////////////////////////////////////////////////////
// PTimeInterval
PTimeInterval::PTimeInterval(long millisecs,
long seconds,
long minutes,
long hours,
int days)
{
SetInterval(millisecs, seconds, minutes, hours, days);
}
PTimeInterval::PTimeInterval(const PString & str)
{
PStringStream strm(str);
ReadFrom(strm);
}
PObject::Comparison PTimeInterval::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PTimeInterval), PInvalidCast);
const PTimeInterval & other = (const PTimeInterval &)obj;
return milliseconds < other.milliseconds ? LessThan :
milliseconds > other.milliseconds ? GreaterThan : EqualTo;
}
void PTimeInterval::PrintOn(ostream & stream) const
{
int precision = stream.precision();
Formats fmt = NormalFormat;
if ((stream.flags()&ios::scientific) != 0)
fmt = SecondsOnly;
else if (precision < 0) {
fmt = IncludeDays;
precision = -precision;
}
stream << AsString(precision, fmt, stream.width());
}
void PTimeInterval::ReadFrom(istream &strm)
{
long day = 0;
long hour = 0;
long min = 0;
float sec;
strm >> sec;
while (strm.peek() == ':') {
day = hour;
hour = min;
min = (long)sec;
strm.get();
strm >> sec;
}
SetInterval(((long)(sec*1000))%1000, (int)sec, min, hour, day);
}
PString PTimeInterval::AsString(int precision, Formats format, int width) const
{
PStringStream str;
if (precision > 3)
precision = 3;
else if (precision < 0)
precision = 0;
PInt64 ms = milliseconds;
if (ms < 0) {
str << '-';
ms = -ms;
}
if (format == SecondsOnly) {
switch (precision) {
case 1 :
str << ms/1000 << '.' << (int)(ms%1000+50)/100;
break;
case 2 :
str << ms/1000 << '.' << setw(2) << (int)(ms%1000+5)/10;
break;
case 3 :
str << ms/1000 << '.' << setw(3) << (int)(ms%1000);
break;
default :
str << (ms+500)/1000;
}
return str;
}
PBoolean hadPrevious = PFalse;
long tmp;
str.fill('0');
if (format == IncludeDays) {
tmp = (long)(ms/86400000);
if (tmp > 0 || width > (precision+10)) {
str << tmp << 'd';
hadPrevious = PTrue;
}
tmp = (long)(ms%86400000)/3600000;
}
else
tmp = (long)(ms/3600000);
if (hadPrevious || tmp > 0 || width > (precision+7)) {
if (hadPrevious)
str.width(2);
str << tmp << ':';
hadPrevious = PTrue;
}
tmp = (long)(ms%3600000)/60000;
if (hadPrevious || tmp > 0 || width > (precision+4)) {
if (hadPrevious)
str.width(2);
str << tmp << ':';
hadPrevious = PTrue;
}
if (hadPrevious)
str.width(2);
str << (long)(ms%60000)/1000;
switch (precision) {
case 1 :
str << '.' << (int)(ms%1000)/100;
break;
case 2 :
str << '.' << setw(2) << (int)(ms%1000)/10;
break;
case 3 :
str << '.' << setw(3) << (int)(ms%1000);
}
return str;
}
void PTimeInterval::SetInterval(PInt64 millisecs,
long seconds,
long minutes,
long hours,
int days)
{
milliseconds = days;
milliseconds *= 24;
milliseconds += hours;
milliseconds *= 60;
milliseconds += minutes;
milliseconds *= 60;
milliseconds += seconds;
milliseconds *= 1000;
milliseconds += millisecs;
}
///////////////////////////////////////////////////////////////////////////////
// PTime
static time_t p_mktime(struct tm * t, int zone)
{
// mktime returns GMT, calculated using input_time - timezone. However, this
// assumes that the input time was a local time. If the input time wasn't a
// local time, then we have have to add the local timezone (without daylight
// savings) and subtract the specified zone offset to get GMT
// and then subtract
t->tm_isdst = PTime::IsDaylightSavings() ? 1 : 0;
time_t theTime = mktime(t);
if (theTime == (time_t)-1)
theTime = 0;
else if (zone != PTime::Local) {
theTime += PTime::GetTimeZone()*60; // convert to local time
if (theTime > (time_t) zone*60)
theTime -= zone*60; // and then to GMT
}
return theTime;
}
PTime::PTime(const PString & str)
{
PStringStream s(str);
ReadFrom(s);
}
PTime::PTime(int second, int minute, int hour,
int day, int month, int year,
int zone)
{
microseconds = 0;
struct tm t;
PAssert(second >= 0 && second <= 59, PInvalidParameter);
t.tm_sec = second;
PAssert(minute >= 0 && minute <= 59, PInvalidParameter);
t.tm_min = minute;
PAssert(hour >= 0 && hour <= 23, PInvalidParameter);
t.tm_hour = hour;
PAssert(day >= 1 && day <= 31, PInvalidParameter);
t.tm_mday = day;
PAssert(month >= 1 && month <= 12, PInvalidParameter);
t.tm_mon = month-1;
PAssert(year >= 1970 && year <= 2038, PInvalidParameter);
t.tm_year = year-1900;
theTime = p_mktime(&t, zone);
}
PObject::Comparison PTime::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PTime), PInvalidCast);
const PTime & other = (const PTime &)obj;
if (theTime < other.theTime)
return LessThan;
if (theTime > other.theTime)
return GreaterThan;
if (microseconds < other.microseconds)
return LessThan;
if (microseconds > other.microseconds)
return GreaterThan;
return EqualTo;
}
PString PTime::AsString(TimeFormat format, int zone) const
{
if (format >= NumTimeStrings)
return "Invalid format : " + AsString("yyyy-MM-dd T hh:mm:ss Z");
switch (format) {
case RFC1123 :
return AsString("wwwe, dd MMME yyyy hh:mm:ss z", zone);
case ShortISO8601 :
return AsString("yyyyMMddThhmmssZ");
case LongISO8601 :
return AsString("yyyy-MM-dd T hh:mm:ss Z");
default :
break;
}
PString fmt, dsep;
PString tsep = GetTimeSeparator();
PBoolean is12hour = GetTimeAMPM();
switch (format ) {
case LongDateTime :
case LongTime :
case MediumDateTime :
case ShortDateTime :
case ShortTime :
if (!is12hour)
fmt = "h";
fmt += "h" + tsep + "mm";
switch (format) {
case LongDateTime :
case LongTime :
fmt += tsep + "ss";
default :
break;
}
if (is12hour)
fmt += "a";
break;
default :
break;
}
switch (format ) {
case LongDateTime :
case MediumDateTime :
case ShortDateTime :
fmt += ' ';
break;
default :
break;
}
switch (format ) {
case LongDateTime :
case LongDate :
fmt += "wwww ";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -