2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "XBDateTime.h"
23 #include "guilib/LocalizeStrings.h"
24 #include "utils/log.h"
25 #include "utils/StringUtils.h"
27 #include "XTimeUtils.h"
28 #include "XFileUtils.h"
33 #define SECONDS_PER_DAY 86400UL
34 #define SECONDS_PER_HOUR 3600UL
35 #define SECONDS_PER_MINUTE 60UL
36 #define SECONDS_TO_FILETIME 10000000UL
38 static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
39 static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
41 /////////////////////////////////////////////////
46 CDateTimeSpan::CDateTimeSpan()
48 m_timeSpan.dwHighDateTime=0;
49 m_timeSpan.dwLowDateTime=0;
52 CDateTimeSpan::CDateTimeSpan(const CDateTimeSpan& span)
54 m_timeSpan.dwHighDateTime=span.m_timeSpan.dwHighDateTime;
55 m_timeSpan.dwLowDateTime=span.m_timeSpan.dwLowDateTime;
58 CDateTimeSpan::CDateTimeSpan(int day, int hour, int minute, int second)
60 SetDateTimeSpan(day, hour, minute, second);
63 bool CDateTimeSpan::operator >(const CDateTimeSpan& right) const
65 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)>0;
68 bool CDateTimeSpan::operator >=(const CDateTimeSpan& right) const
70 return operator >(right) || operator ==(right);
73 bool CDateTimeSpan::operator <(const CDateTimeSpan& right) const
75 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)<0;
78 bool CDateTimeSpan::operator <=(const CDateTimeSpan& right) const
80 return operator <(right) || operator ==(right);
83 bool CDateTimeSpan::operator ==(const CDateTimeSpan& right) const
85 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)==0;
88 bool CDateTimeSpan::operator !=(const CDateTimeSpan& right) const
90 return !operator ==(right);
93 CDateTimeSpan CDateTimeSpan::operator +(const CDateTimeSpan& right) const
95 CDateTimeSpan left(*this);
97 ULARGE_INTEGER timeLeft;
98 left.ToULargeInt(timeLeft);
100 ULARGE_INTEGER timeRight;
101 right.ToULargeInt(timeRight);
103 timeLeft.QuadPart+=timeRight.QuadPart;
105 left.FromULargeInt(timeLeft);
110 CDateTimeSpan CDateTimeSpan::operator -(const CDateTimeSpan& right) const
112 CDateTimeSpan left(*this);
114 ULARGE_INTEGER timeLeft;
115 left.ToULargeInt(timeLeft);
117 ULARGE_INTEGER timeRight;
118 right.ToULargeInt(timeRight);
120 timeLeft.QuadPart-=timeRight.QuadPart;
122 left.FromULargeInt(timeLeft);
127 const CDateTimeSpan& CDateTimeSpan::operator +=(const CDateTimeSpan& right)
129 ULARGE_INTEGER timeThis;
130 ToULargeInt(timeThis);
132 ULARGE_INTEGER timeRight;
133 right.ToULargeInt(timeRight);
135 timeThis.QuadPart+=timeRight.QuadPart;
137 FromULargeInt(timeThis);
142 const CDateTimeSpan& CDateTimeSpan::operator -=(const CDateTimeSpan& right)
144 ULARGE_INTEGER timeThis;
145 ToULargeInt(timeThis);
147 ULARGE_INTEGER timeRight;
148 right.ToULargeInt(timeRight);
150 timeThis.QuadPart-=timeRight.QuadPart;
152 FromULargeInt(timeThis);
157 void CDateTimeSpan::ToULargeInt(ULARGE_INTEGER& time) const
159 time.u.HighPart=m_timeSpan.dwHighDateTime;
160 time.u.LowPart=m_timeSpan.dwLowDateTime;
163 void CDateTimeSpan::FromULargeInt(const ULARGE_INTEGER& time)
165 m_timeSpan.dwHighDateTime=time.u.HighPart;
166 m_timeSpan.dwLowDateTime=time.u.LowPart;
169 void CDateTimeSpan::SetDateTimeSpan(int day, int hour, int minute, int second)
174 time.QuadPart=(LONGLONG)day*SECONDS_PER_DAY*SECONDS_TO_FILETIME;
175 time.QuadPart+=(LONGLONG)hour*SECONDS_PER_HOUR*SECONDS_TO_FILETIME;
176 time.QuadPart+=(LONGLONG)minute*SECONDS_PER_MINUTE*SECONDS_TO_FILETIME;
177 time.QuadPart+=(LONGLONG)second*SECONDS_TO_FILETIME;
182 void CDateTimeSpan::SetFromTimeString(const CStdString& time) // hh:mm
184 if (time.size() >= 5 && time[2] == ':')
186 int hour = atoi(time.substr(0, 2).c_str());
187 int minutes = atoi(time.substr(3, 2).c_str());
188 SetDateTimeSpan(0,hour,minutes,0);
192 int CDateTimeSpan::GetDays() const
197 return (int)(time.QuadPart/SECONDS_TO_FILETIME)/SECONDS_PER_DAY;
200 int CDateTimeSpan::GetHours() const
205 return (int)((time.QuadPart/SECONDS_TO_FILETIME)%SECONDS_PER_DAY)/SECONDS_PER_HOUR;
208 int CDateTimeSpan::GetMinutes() const
213 return (int)((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)/SECONDS_PER_MINUTE;
216 int CDateTimeSpan::GetSeconds() const
221 return (int)(((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)%SECONDS_PER_MINUTE)%SECONDS_PER_MINUTE;
224 int CDateTimeSpan::GetSecondsTotal() const
229 return (int)(time.QuadPart/SECONDS_TO_FILETIME);
232 void CDateTimeSpan::SetFromPeriod(const CStdString &period)
234 long days = atoi(period.c_str());
235 // find the first non-space and non-number
236 size_t pos = period.find_first_not_of("0123456789 ", 0);
237 if (pos != std::string::npos)
239 CStdString units = period.substr(pos, 3);
240 if (StringUtils::EqualsNoCase(units, "wee"))
242 else if (StringUtils::EqualsNoCase(units, "mon"))
246 SetDateTimeSpan(days, 0, 0, 0);
249 /////////////////////////////////////////////////
254 CDateTime::CDateTime()
259 CDateTime::CDateTime(const SYSTEMTIME &time)
261 // we store internally as a FILETIME
262 m_state = ToFileTime(time, m_time) ? valid : invalid;
265 CDateTime::CDateTime(const FILETIME &time)
271 CDateTime::CDateTime(const CDateTime& time)
274 m_state=time.m_state;
277 CDateTime::CDateTime(const time_t& time)
279 m_state = ToFileTime(time, m_time) ? valid : invalid;
282 CDateTime::CDateTime(const tm& time)
284 m_state = ToFileTime(time, m_time) ? valid : invalid;
287 CDateTime::CDateTime(int year, int month, int day, int hour, int minute, int second)
289 SetDateTime(year, month, day, hour, minute, second);
292 CDateTime CDateTime::GetCurrentDateTime()
294 // get the current time
298 return CDateTime(time);
301 CDateTime CDateTime::GetUTCDateTime()
303 CDateTime time(GetCurrentDateTime());
304 time += GetTimezoneBias();
308 const CDateTime& CDateTime::operator =(const SYSTEMTIME& right)
310 m_state = ToFileTime(right, m_time) ? valid : invalid;
315 const CDateTime& CDateTime::operator =(const FILETIME& right)
323 const CDateTime& CDateTime::operator =(const time_t& right)
325 m_state = ToFileTime(right, m_time) ? valid : invalid;
330 const CDateTime& CDateTime::operator =(const tm& right)
332 m_state = ToFileTime(right, m_time) ? valid : invalid;
337 bool CDateTime::operator >(const CDateTime& right) const
339 return operator >(right.m_time);
342 bool CDateTime::operator >=(const CDateTime& right) const
344 return operator >(right) || operator ==(right);
347 bool CDateTime::operator <(const CDateTime& right) const
349 return operator <(right.m_time);
352 bool CDateTime::operator <=(const CDateTime& right) const
354 return operator <(right) || operator ==(right);
357 bool CDateTime::operator ==(const CDateTime& right) const
359 return operator ==(right.m_time);
362 bool CDateTime::operator !=(const CDateTime& right) const
364 return !operator ==(right);
367 bool CDateTime::operator >(const FILETIME& right) const
369 return CompareFileTime(&m_time, &right)>0;
372 bool CDateTime::operator >=(const FILETIME& right) const
374 return operator >(right) || operator ==(right);
377 bool CDateTime::operator <(const FILETIME& right) const
379 return CompareFileTime(&m_time, &right)<0;
382 bool CDateTime::operator <=(const FILETIME& right) const
384 return operator <(right) || operator ==(right);
387 bool CDateTime::operator ==(const FILETIME& right) const
389 return CompareFileTime(&m_time, &right)==0;
392 bool CDateTime::operator !=(const FILETIME& right) const
394 return !operator ==(right);
397 bool CDateTime::operator >(const SYSTEMTIME& right) const
400 ToFileTime(right, time);
402 return operator >(time);
405 bool CDateTime::operator >=(const SYSTEMTIME& right) const
407 return operator >(right) || operator ==(right);
410 bool CDateTime::operator <(const SYSTEMTIME& right) const
413 ToFileTime(right, time);
415 return operator <(time);
418 bool CDateTime::operator <=(const SYSTEMTIME& right) const
420 return operator <(right) || operator ==(right);
423 bool CDateTime::operator ==(const SYSTEMTIME& right) const
426 ToFileTime(right, time);
428 return operator ==(time);
431 bool CDateTime::operator !=(const SYSTEMTIME& right) const
433 return !operator ==(right);
436 bool CDateTime::operator >(const time_t& right) const
439 ToFileTime(right, time);
441 return operator >(time);
444 bool CDateTime::operator >=(const time_t& right) const
446 return operator >(right) || operator ==(right);
449 bool CDateTime::operator <(const time_t& right) const
452 ToFileTime(right, time);
454 return operator <(time);
457 bool CDateTime::operator <=(const time_t& right) const
459 return operator <(right) || operator ==(right);
462 bool CDateTime::operator ==(const time_t& right) const
465 ToFileTime(right, time);
467 return operator ==(time);
470 bool CDateTime::operator !=(const time_t& right) const
472 return !operator ==(right);
475 bool CDateTime::operator >(const tm& right) const
478 ToFileTime(right, time);
480 return operator >(time);
483 bool CDateTime::operator >=(const tm& right) const
485 return operator >(right) || operator ==(right);
488 bool CDateTime::operator <(const tm& right) const
491 ToFileTime(right, time);
493 return operator <(time);
496 bool CDateTime::operator <=(const tm& right) const
498 return operator <(right) || operator ==(right);
501 bool CDateTime::operator ==(const tm& right) const
504 ToFileTime(right, time);
506 return operator ==(time);
509 bool CDateTime::operator !=(const tm& right) const
511 return !operator ==(right);
514 CDateTime CDateTime::operator +(const CDateTimeSpan& right) const
516 CDateTime left(*this);
518 ULARGE_INTEGER timeLeft;
519 left.ToULargeInt(timeLeft);
521 ULARGE_INTEGER timeRight;
522 right.ToULargeInt(timeRight);
524 timeLeft.QuadPart+=timeRight.QuadPart;
526 left.FromULargeInt(timeLeft);
531 CDateTime CDateTime::operator -(const CDateTimeSpan& right) const
533 CDateTime left(*this);
535 ULARGE_INTEGER timeLeft;
536 left.ToULargeInt(timeLeft);
538 ULARGE_INTEGER timeRight;
539 right.ToULargeInt(timeRight);
541 timeLeft.QuadPart-=timeRight.QuadPart;
543 left.FromULargeInt(timeLeft);
548 const CDateTime& CDateTime::operator +=(const CDateTimeSpan& right)
550 ULARGE_INTEGER timeThis;
551 ToULargeInt(timeThis);
553 ULARGE_INTEGER timeRight;
554 right.ToULargeInt(timeRight);
556 timeThis.QuadPart+=timeRight.QuadPart;
558 FromULargeInt(timeThis);
563 const CDateTime& CDateTime::operator -=(const CDateTimeSpan& right)
565 ULARGE_INTEGER timeThis;
566 ToULargeInt(timeThis);
568 ULARGE_INTEGER timeRight;
569 right.ToULargeInt(timeRight);
571 timeThis.QuadPart-=timeRight.QuadPart;
573 FromULargeInt(timeThis);
578 CDateTimeSpan CDateTime::operator -(const CDateTime& right) const
582 ULARGE_INTEGER timeLeft;
583 left.ToULargeInt(timeLeft);
585 ULARGE_INTEGER timeThis;
586 ToULargeInt(timeThis);
588 ULARGE_INTEGER timeRight;
589 right.ToULargeInt(timeRight);
591 timeLeft.QuadPart=timeThis.QuadPart-timeRight.QuadPart;
593 left.FromULargeInt(timeLeft);
598 CDateTime::operator FILETIME() const
603 void CDateTime::Archive(CArchive& ar)
620 m_state = CDateTime::STATE(state);
625 ToFileTime(st, m_time);
630 void CDateTime::Reset()
632 SetDateTime(1601, 1, 1, 0, 0, 0);
636 void CDateTime::SetValid(bool yesNo)
638 m_state=yesNo ? valid : invalid;
641 bool CDateTime::IsValid() const
643 return m_state==valid;
646 bool CDateTime::ToFileTime(const SYSTEMTIME& time, FILETIME& fileTime) const
648 return SystemTimeToFileTime(&time, &fileTime) == TRUE &&
649 (fileTime.dwLowDateTime > 0 || fileTime.dwHighDateTime > 0);
652 bool CDateTime::ToFileTime(const time_t& time, FILETIME& fileTime) const
654 LONGLONG ll = Int32x32To64(time, 10000000)+0x19DB1DED53E8000LL;
656 fileTime.dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
657 fileTime.dwHighDateTime = (DWORD)(ll >> 32);
662 bool CDateTime::ToFileTime(const tm& time, FILETIME& fileTime) const
665 ZeroMemory(&st, sizeof(SYSTEMTIME));
667 st.wYear=time.tm_year+1900;
668 st.wMonth=time.tm_mon+1;
669 st.wDayOfWeek=time.tm_wday;
670 st.wDay=time.tm_mday;
671 st.wHour=time.tm_hour;
672 st.wMinute=time.tm_min;
673 st.wSecond=time.tm_sec;
675 return SystemTimeToFileTime(&st, &fileTime)==TRUE;
678 void CDateTime::ToULargeInt(ULARGE_INTEGER& time) const
680 time.u.HighPart=m_time.dwHighDateTime;
681 time.u.LowPart=m_time.dwLowDateTime;
684 void CDateTime::FromULargeInt(const ULARGE_INTEGER& time)
686 m_time.dwHighDateTime=time.u.HighPart;
687 m_time.dwLowDateTime=time.u.LowPart;
690 bool CDateTime::SetFromDateString(const CStdString &date)
692 /* TODO:STRING_CLEANUP */
699 if (SetFromDBDate(date))
702 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december",NULL};
704 size_t iDayPos = date.find("day");
705 size_t iPos = date.find(" ");
706 if (iDayPos < iPos && iDayPos != std::string::npos)
709 iPos = date.find(" ", iPos+1);
714 CStdString strMonth = date.substr(iDayPos, iPos - iDayPos);
715 if (strMonth.empty())
718 size_t iPos2 = date.find(",");
719 CStdString strDay = (date.size() >= iPos) ? date.substr(iPos, iPos2-iPos) : "";
720 CStdString strYear = date.substr(date.find(" ", iPos2) + 1);
721 while (months[j] && stricmp(strMonth.c_str(),months[j]) != 0)
726 return SetDateTime(atol(strYear.c_str()),j+1,atol(strDay.c_str()),0,0,0);
729 int CDateTime::GetDay() const
737 int CDateTime::GetMonth() const
745 int CDateTime::GetYear() const
753 int CDateTime::GetHour() const
761 int CDateTime::GetMinute() const
769 int CDateTime::GetSecond() const
777 int CDateTime::GetDayOfWeek() const
782 return st.wDayOfWeek;
785 int CDateTime::GetMinuteOfDay() const
789 return st.wHour*60+st.wMinute;
792 bool CDateTime::SetDateTime(int year, int month, int day, int hour, int minute, int second)
795 ZeroMemory(&st, sizeof(SYSTEMTIME));
804 m_state = ToFileTime(st, m_time) ? valid : invalid;
805 return m_state == valid;
808 bool CDateTime::SetDate(int year, int month, int day)
810 return SetDateTime(year, month, day, 0, 0, 0);
813 bool CDateTime::SetTime(int hour, int minute, int second)
815 // 01.01.1601 00:00:00 is 0 as filetime
816 return SetDateTime(1601, 1, 1, hour, minute, second);
819 void CDateTime::GetAsSystemTime(SYSTEMTIME& time) const
821 FileTimeToSystemTime(&m_time, &time);
824 #define UNIX_BASE_TIME 116444736000000000LL /* nanoseconds since epoch */
825 void CDateTime::GetAsTime(time_t& time) const
828 ll = ((LONGLONG)m_time.dwHighDateTime << 32) + m_time.dwLowDateTime;
829 time=(time_t)((ll - UNIX_BASE_TIME) / 10000000);
832 void CDateTime::GetAsTm(tm& time) const
837 time.tm_year=st.wYear-1900;
838 time.tm_mon=st.wMonth-1;
839 time.tm_wday=st.wDayOfWeek;
840 time.tm_mday=st.wDay;
841 time.tm_hour=st.wHour;
842 time.tm_min=st.wMinute;
843 time.tm_sec=st.wSecond;
848 void CDateTime::GetAsTimeStamp(FILETIME& time) const
850 ::LocalFileTimeToFileTime(&m_time, &time);
853 CStdString CDateTime::GetAsDBDate() const
858 return StringUtils::Format("%04i-%02i-%02i", st.wYear, st.wMonth, st.wDay);
861 CStdString CDateTime::GetAsDBDateTime() const
866 return StringUtils::Format("%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
869 CStdString CDateTime::GetAsSaveString() const
874 return StringUtils::Format("%04i%02i%02i_%02i%02i%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);;
877 bool CDateTime::SetFromUTCDateTime(const CDateTime &dateTime)
879 CDateTime tmp(dateTime);
880 tmp -= GetTimezoneBias();
883 m_state = tmp.m_state;
884 return m_state == valid;
887 static bool bGotTimezoneBias = false;
889 void CDateTime::ResetTimezoneBias(void)
891 bGotTimezoneBias = false;
894 CDateTimeSpan CDateTime::GetTimezoneBias(void)
896 static CDateTimeSpan timezoneBias;
898 if (!bGotTimezoneBias)
900 bGotTimezoneBias = true;
901 TIME_ZONE_INFORMATION tz;
902 switch(GetTimeZoneInformation(&tz))
904 case TIME_ZONE_ID_DAYLIGHT:
905 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.DaylightBias, 0);
907 case TIME_ZONE_ID_STANDARD:
908 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.StandardBias, 0);
910 case TIME_ZONE_ID_UNKNOWN:
911 timezoneBias = CDateTimeSpan(0, 0, tz.Bias, 0);
919 bool CDateTime::SetFromUTCDateTime(const time_t &dateTime)
921 CDateTime tmp(dateTime);
922 return SetFromUTCDateTime(tmp);
925 bool CDateTime::SetFromW3CDate(const CStdString &dateTime)
927 CStdString date, time, zone;
929 size_t posT = dateTime.find("T");
930 if(posT != std::string::npos)
932 date = dateTime.substr(0, posT);
933 CStdString::size_type posZ = dateTime.find_first_of("+-Z", posT);
934 if(posZ == CStdString::npos)
935 time = dateTime.substr(posT + 1);
938 time = dateTime.substr(posT + 1, posZ - posT - 1);
939 zone = dateTime.substr(posZ);
945 int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
947 if (date.size() >= 4)
948 year = atoi(date.substr(0, 4).c_str());
950 if (date.size() >= 10)
952 month = atoi(date.substr(5, 2).c_str());
953 day = atoi(date.substr(8, 2).c_str());
956 if (time.length() >= 5)
958 hour = atoi(time.substr(0, 2).c_str());
959 min = atoi(time.substr(3, 2).c_str());
962 if (time.length() >= 8)
963 sec = atoi(time.substr(6, 2).c_str());
965 return SetDateTime(year, month, day, hour, min, sec);
968 bool CDateTime::SetFromDBDateTime(const CStdString &dateTime)
970 // assumes format YYYY-MM-DD HH:MM:SS
971 if (dateTime.size() == 19)
973 int year = atoi(dateTime.substr(0, 4).c_str());
974 int month = atoi(dateTime.substr(5, 2).c_str());
975 int day = atoi(dateTime.substr(8, 2).c_str());
976 int hour = atoi(dateTime.substr(11, 2).c_str());
977 int min = atoi(dateTime.substr(14, 2).c_str());
978 int sec = atoi(dateTime.substr(17, 2).c_str());
979 return SetDateTime(year, month, day, hour, min, sec);
984 bool CDateTime::SetFromDBDate(const CStdString &date)
986 if (date.size() < 10)
989 // YYYY-MM-DD or DD-MM-YYYY
990 const static std::string sep_chars = "-./";
991 int year = 0, month = 0, day = 0;
992 if (sep_chars.find(date[2]) != std::string::npos)
994 day = atoi(date.substr(0, 2).c_str());
995 month = atoi(date.substr(3, 2).c_str());
996 year = atoi(date.substr(6, 4).c_str());
998 else if (sep_chars.find(date[4]) != std::string::npos)
1000 year = atoi(date.substr(0, 4).c_str());
1001 month = atoi(date.substr(5, 2).c_str());
1002 day = atoi(date.substr(8, 2).c_str());
1004 return SetDate(year, month, day);
1007 bool CDateTime::SetFromDBTime(const CStdString &time)
1009 if (time.size() < 8)
1013 int hour, minute, second;
1015 hour = atoi(time.substr(0, 2).c_str());
1016 minute = atoi(time.substr(3, 2).c_str());
1017 second = atoi(time.substr(6, 2).c_str());
1019 return SetTime(hour, minute, second);
1022 bool CDateTime::SetFromRFC1123DateTime(const CStdString &dateTime)
1024 CStdString date = dateTime;
1025 StringUtils::Trim(date);
1027 if (date.size() != 29)
1030 int day = strtol(date.substr(5, 2).c_str(), NULL, 10);
1032 CStdString strMonth = date.substr(8, 3);
1034 for (unsigned int index = 0; index < 12; index++)
1036 if (strMonth.Equals(MONTH_NAMES[index]))
1046 int year = strtol(date.substr(12, 4).c_str(), NULL, 10);
1047 int hour = strtol(date.substr(17, 2).c_str(), NULL, 10);
1048 int min = strtol(date.substr(20, 2).c_str(), NULL, 10);
1049 int sec = strtol(date.substr(23, 2).c_str(), NULL, 10);
1051 return SetDateTime(year, month, day, hour, min, sec);
1054 CStdString CDateTime::GetAsLocalizedTime(const CStdString &format, bool withSeconds) const
1057 const CStdString& strFormat = format.empty() ? g_langInfo.GetTimeFormat() : format;
1059 SYSTEMTIME dateTime;
1060 GetAsSystemTime(dateTime);
1062 // Prefetch meridiem symbol
1063 const CStdString& strMeridiem=g_langInfo.GetMeridiemSymbol(dateTime.wHour > 11 ? CLangInfo::MERIDIEM_SYMBOL_PM : CLangInfo::MERIDIEM_SYMBOL_AM);
1065 size_t length = strFormat.size();
1066 for (size_t i=0; i < length; ++i)
1068 char c=strFormat[i];
1071 // To be able to display a "'" in the string,
1072 // find the last "'" that doesn't follow a "'"
1074 while(((pos = strFormat.find(c, pos + 1)) != std::string::npos &&
1075 pos<strFormat.size()) && strFormat[pos+1]=='\'') {}
1078 if (pos != std::string::npos)
1080 // Extract string between ' '
1081 strPart=strFormat.substr(i + 1, pos - i - 1);
1086 strPart=strFormat.substr(i + 1, length - i - 1);
1090 StringUtils::Replace(strPart, "''", "'");
1094 else if (c=='h' || c=='H') // parse hour (H="24 hour clock")
1098 int pos=strFormat.find_first_not_of(c,i+1);
1101 // Get length of the hour mask, eg. HH
1107 // mask ends at the end of the string, extract it
1108 partLength=length-i;
1112 int hour=dateTime.wHour;
1114 { // recalc to 12 hour clock
1116 hour -= (12 * (hour > 12));
1118 hour += (12 * (hour < 1));
1121 // Format hour string with the length of the mask
1124 str = StringUtils::Format("%d", hour);
1126 str = StringUtils::Format("%02d", hour);
1130 else if (c=='m') // parse minutes
1134 int pos=strFormat.find_first_not_of(c,i+1);
1137 // Get length of the minute mask, eg. mm
1143 // mask ends at the end of the string, extract it
1144 partLength=length-i;
1148 // Format minute string with the length of the mask
1151 str = StringUtils::Format("%d", dateTime.wMinute);
1153 str = StringUtils::Format("%02d", dateTime.wMinute);
1157 else if (c=='s') // parse seconds
1161 int pos=strFormat.find_first_not_of(c,i+1);
1164 // Get length of the seconds mask, eg. ss
1170 // mask ends at the end of the string, extract it
1171 partLength=length-i;
1177 // Format seconds string with the length of the mask
1180 str = StringUtils::Format("%d", dateTime.wSecond);
1182 str = StringUtils::Format("%02d", dateTime.wSecond);
1187 strOut.erase(strOut.size()-1,1);
1189 else if (c=='x') // add meridiem symbol
1191 int pos=strFormat.find_first_not_of(c,i+1);
1194 // Get length of the meridiem mask
1199 // mask ends at the end of the string, extract it
1203 strOut+=strMeridiem;
1205 else // everything else pass to output
1212 CStdString CDateTime::GetAsLocalizedDate(bool longDate/*=false*/, bool withShortNames/*=true*/) const
1214 return GetAsLocalizedDate(g_langInfo.GetDateFormat(longDate), withShortNames);
1217 CStdString CDateTime::GetAsLocalizedDate(const CStdString &strFormat, bool withShortNames/*=true*/) const
1221 SYSTEMTIME dateTime;
1222 GetAsSystemTime(dateTime);
1224 size_t length = strFormat.size();
1225 for (size_t i = 0; i < length; ++i)
1227 char c=strFormat[i];
1230 // To be able to display a "'" in the string,
1231 // find the last "'" that doesn't follow a "'"
1233 while(((pos = strFormat.find(c, pos + 1)) != std::string::npos &&
1234 pos < strFormat.size()) &&
1235 strFormat[pos + 1] == '\'') {}
1238 if (pos != std::string::npos)
1240 // Extract string between ' '
1241 strPart = strFormat.substr(i + 1, pos - i - 1);
1246 strPart = strFormat.substr(i + 1, length - i - 1);
1249 StringUtils::Replace(strPart, "''", "'");
1252 else if (c=='D' || c=='d') // parse days
1254 size_t partLength=0;
1256 size_t pos = strFormat.find_first_not_of(c, i+1);
1257 if (pos != std::string::npos)
1259 // Get length of the day mask, eg. DDDD
1265 // mask ends at the end of the string, extract it
1266 partLength=length-i;
1270 // Format string with the length of the mask
1272 if (partLength==1) // single-digit number
1273 str = StringUtils::Format("%d", dateTime.wDay);
1274 else if (partLength==2) // two-digit number
1275 str = StringUtils::Format("%02d", dateTime.wDay);
1276 else // Day of week string
1278 int wday = dateTime.wDayOfWeek;
1279 if (wday < 1 || wday > 7) wday = 7;
1280 str = g_localizeStrings.Get(((withShortNames || c =='d') ? 40 : 10) + wday);
1284 else if (c=='M' || c=='m') // parse month
1286 size_t partLength=0;
1288 size_t pos=strFormat.find_first_not_of(c,i+1);
1289 if (pos != std::string::npos)
1291 // Get length of the month mask, eg. MMMM
1297 // mask ends at the end of the string, extract it
1298 partLength=length-i;
1302 // Format string with the length of the mask
1304 if (partLength==1) // single-digit number
1305 str = StringUtils::Format("%d", dateTime.wMonth);
1306 else if (partLength==2) // two-digit number
1307 str = StringUtils::Format("%02d", dateTime.wMonth);
1308 else // Month string
1310 int wmonth = dateTime.wMonth;
1311 if (wmonth < 1 || wmonth > 12) wmonth = 12;
1312 str = g_localizeStrings.Get(((withShortNames || c =='m') ? 50 : 20) + wmonth);
1316 else if (c=='Y' || c =='y') // parse year
1318 size_t partLength = 0;
1320 size_t pos = strFormat.find_first_not_of(c,i+1);
1321 if (pos != std::string::npos)
1323 // Get length of the year mask, eg. YYYY
1329 // mask ends at the end of the string, extract it
1330 partLength=length-i;
1334 // Format string with the length of the mask
1335 CStdString str = StringUtils::Format("%d", dateTime.wYear); // four-digit number
1336 if (partLength <= 2)
1337 str.erase(0, 2); // two-digit number
1341 else // everything else pass to output
1348 CStdString CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withSeconds/*=true*/) const
1350 return GetAsLocalizedDate(longDate)+" "+GetAsLocalizedTime("", withSeconds);
1353 CDateTime CDateTime::GetAsUTCDateTime() const
1355 CDateTime time(m_time);
1356 time += GetTimezoneBias();
1360 CStdString CDateTime::GetAsRFC1123DateTime() const
1362 CDateTime time(GetAsUTCDateTime());
1364 int weekDay = time.GetDayOfWeek();
1367 else if (weekDay > 6)
1369 if (weekDay != time.GetDayOfWeek())
1370 CLog::Log(LOGWARNING, "Invalid day of week %d in %s", time.GetDayOfWeek(), time.GetAsDBDateTime().c_str());
1372 int month = time.GetMonth();
1375 else if (month > 12)
1377 if (month != time.GetMonth())
1378 CLog::Log(LOGWARNING, "Invalid month %d in %s", time.GetMonth(), time.GetAsDBDateTime().c_str());
1380 CStdString result = StringUtils::Format("%s, %02i %s %04i %02i:%02i:%02i GMT", DAY_NAMES[weekDay], time.GetDay(), MONTH_NAMES[month - 1], time.GetYear(), time.GetHour(), time.GetMinute(), time.GetSecond());
1384 int CDateTime::MonthStringToMonthNum(const CStdString& month)
1386 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december"};
1387 const char* abr_months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
1390 for (; i < 12 && !StringUtils::EqualsNoCase(month, months[i]) && !StringUtils::EqualsNoCase(month, abr_months[i]); i++);