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"
26 #define SECONDS_PER_DAY 86400UL
27 #define SECONDS_PER_HOUR 3600UL
28 #define SECONDS_PER_MINUTE 60UL
29 #define SECONDS_TO_FILETIME 10000000UL
31 static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
32 static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
34 /////////////////////////////////////////////////
39 CDateTimeSpan::CDateTimeSpan()
41 m_timeSpan.dwHighDateTime=0;
42 m_timeSpan.dwLowDateTime=0;
45 CDateTimeSpan::CDateTimeSpan(const CDateTimeSpan& span)
47 m_timeSpan.dwHighDateTime=span.m_timeSpan.dwHighDateTime;
48 m_timeSpan.dwLowDateTime=span.m_timeSpan.dwLowDateTime;
51 CDateTimeSpan::CDateTimeSpan(int day, int hour, int minute, int second)
53 SetDateTimeSpan(day, hour, minute, second);
56 bool CDateTimeSpan::operator >(const CDateTimeSpan& right) const
58 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)>0;
61 bool CDateTimeSpan::operator >=(const CDateTimeSpan& right) const
63 return operator >(right) || operator ==(right);
66 bool CDateTimeSpan::operator <(const CDateTimeSpan& right) const
68 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)<0;
71 bool CDateTimeSpan::operator <=(const CDateTimeSpan& right) const
73 return operator <(right) || operator ==(right);
76 bool CDateTimeSpan::operator ==(const CDateTimeSpan& right) const
78 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)==0;
81 bool CDateTimeSpan::operator !=(const CDateTimeSpan& right) const
83 return !operator ==(right);
86 CDateTimeSpan CDateTimeSpan::operator +(const CDateTimeSpan& right) const
88 CDateTimeSpan left(*this);
90 ULARGE_INTEGER timeLeft;
91 left.ToULargeInt(timeLeft);
93 ULARGE_INTEGER timeRight;
94 right.ToULargeInt(timeRight);
96 timeLeft.QuadPart+=timeRight.QuadPart;
98 left.FromULargeInt(timeLeft);
103 CDateTimeSpan CDateTimeSpan::operator -(const CDateTimeSpan& right) const
105 CDateTimeSpan left(*this);
107 ULARGE_INTEGER timeLeft;
108 left.ToULargeInt(timeLeft);
110 ULARGE_INTEGER timeRight;
111 right.ToULargeInt(timeRight);
113 timeLeft.QuadPart-=timeRight.QuadPart;
115 left.FromULargeInt(timeLeft);
120 const CDateTimeSpan& CDateTimeSpan::operator +=(const CDateTimeSpan& right)
122 ULARGE_INTEGER timeThis;
123 ToULargeInt(timeThis);
125 ULARGE_INTEGER timeRight;
126 right.ToULargeInt(timeRight);
128 timeThis.QuadPart+=timeRight.QuadPart;
130 FromULargeInt(timeThis);
135 const CDateTimeSpan& CDateTimeSpan::operator -=(const CDateTimeSpan& right)
137 ULARGE_INTEGER timeThis;
138 ToULargeInt(timeThis);
140 ULARGE_INTEGER timeRight;
141 right.ToULargeInt(timeRight);
143 timeThis.QuadPart-=timeRight.QuadPart;
145 FromULargeInt(timeThis);
150 void CDateTimeSpan::ToULargeInt(ULARGE_INTEGER& time) const
152 time.u.HighPart=m_timeSpan.dwHighDateTime;
153 time.u.LowPart=m_timeSpan.dwLowDateTime;
156 void CDateTimeSpan::FromULargeInt(const ULARGE_INTEGER& time)
158 m_timeSpan.dwHighDateTime=time.u.HighPart;
159 m_timeSpan.dwLowDateTime=time.u.LowPart;
162 void CDateTimeSpan::SetDateTimeSpan(int day, int hour, int minute, int second)
167 time.QuadPart=(LONGLONG)day*SECONDS_PER_DAY*SECONDS_TO_FILETIME;
168 time.QuadPart+=(LONGLONG)hour*SECONDS_PER_HOUR*SECONDS_TO_FILETIME;
169 time.QuadPart+=(LONGLONG)minute*SECONDS_PER_MINUTE*SECONDS_TO_FILETIME;
170 time.QuadPart+=(LONGLONG)second*SECONDS_TO_FILETIME;
175 void CDateTimeSpan::SetFromTimeString(const CStdString& time) // hh:mm
177 int hour = atoi(time.Mid(0,2).c_str());
178 int minutes = atoi(time.Mid(3,2).c_str());
179 SetDateTimeSpan(0,hour,minutes,0);
182 int CDateTimeSpan::GetDays() const
187 return (int)(time.QuadPart/SECONDS_TO_FILETIME)/SECONDS_PER_DAY;
190 int CDateTimeSpan::GetHours() const
195 return (int)((time.QuadPart/SECONDS_TO_FILETIME)%SECONDS_PER_DAY)/SECONDS_PER_HOUR;
198 int CDateTimeSpan::GetMinutes() const
203 return (int)((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)/SECONDS_PER_MINUTE;
206 int CDateTimeSpan::GetSeconds() const
211 return (int)(((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)%SECONDS_PER_MINUTE)%SECONDS_PER_MINUTE;
214 int CDateTimeSpan::GetSecondsTotal() const
219 return (int)(time.QuadPart/SECONDS_TO_FILETIME);
222 void CDateTimeSpan::SetFromPeriod(const CStdString &period)
224 long days = atoi(period.c_str());
225 // find the first non-space and non-number
226 int pos = period.find_first_not_of("0123456789 ", 0);
229 CStdString units = period.Mid(pos, 3);
230 if (units.CompareNoCase("wee") == 0)
232 else if (units.CompareNoCase("mon") == 0)
236 SetDateTimeSpan(days, 0, 0, 0);
239 /////////////////////////////////////////////////
244 CDateTime::CDateTime()
249 CDateTime::CDateTime(const SYSTEMTIME &time)
251 // we store internally as a FILETIME
252 m_state = ToFileTime(time, m_time) ? valid : invalid;
255 CDateTime::CDateTime(const FILETIME &time)
261 CDateTime::CDateTime(const CDateTime& time)
264 m_state=time.m_state;
267 CDateTime::CDateTime(const time_t& time)
269 m_state = ToFileTime(time, m_time) ? valid : invalid;
272 CDateTime::CDateTime(const tm& time)
274 m_state = ToFileTime(time, m_time) ? valid : invalid;
277 CDateTime::CDateTime(int year, int month, int day, int hour, int minute, int second)
279 SetDateTime(year, month, day, hour, minute, second);
282 CDateTime CDateTime::GetCurrentDateTime()
284 // get the current time
288 return CDateTime(time);
291 CDateTime CDateTime::GetUTCDateTime()
293 CDateTime time(GetCurrentDateTime());
294 time += GetTimezoneBias();
298 const CDateTime& CDateTime::operator =(const SYSTEMTIME& right)
300 m_state = ToFileTime(right, m_time) ? valid : invalid;
305 const CDateTime& CDateTime::operator =(const FILETIME& right)
313 const CDateTime& CDateTime::operator =(const time_t& right)
315 m_state = ToFileTime(right, m_time) ? valid : invalid;
320 const CDateTime& CDateTime::operator =(const tm& right)
322 m_state = ToFileTime(right, m_time) ? valid : invalid;
327 bool CDateTime::operator >(const CDateTime& right) const
329 return operator >(right.m_time);
332 bool CDateTime::operator >=(const CDateTime& right) const
334 return operator >(right) || operator ==(right);
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);
357 bool CDateTime::operator >(const FILETIME& right) const
359 return CompareFileTime(&m_time, &right)>0;
362 bool CDateTime::operator >=(const FILETIME& right) const
364 return operator >(right) || 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);
387 bool CDateTime::operator >(const SYSTEMTIME& right) const
390 ToFileTime(right, time);
392 return operator >(time);
395 bool CDateTime::operator >=(const SYSTEMTIME& right) const
397 return operator >(right) || operator ==(right);
400 bool CDateTime::operator <(const SYSTEMTIME& right) const
403 ToFileTime(right, time);
405 return operator <(time);
408 bool CDateTime::operator <=(const SYSTEMTIME& right) const
410 return operator <(right) || operator ==(right);
413 bool CDateTime::operator ==(const SYSTEMTIME& right) const
416 ToFileTime(right, time);
418 return operator ==(time);
421 bool CDateTime::operator !=(const SYSTEMTIME& right) const
423 return !operator ==(right);
426 bool CDateTime::operator >(const time_t& right) const
429 ToFileTime(right, time);
431 return operator >(time);
434 bool CDateTime::operator >=(const time_t& right) const
436 return operator >(right) || operator ==(right);
439 bool CDateTime::operator <(const time_t& right) const
442 ToFileTime(right, time);
444 return operator <(time);
447 bool CDateTime::operator <=(const time_t& right) const
449 return operator <(right) || operator ==(right);
452 bool CDateTime::operator ==(const time_t& right) const
455 ToFileTime(right, time);
457 return operator ==(time);
460 bool CDateTime::operator !=(const time_t& right) const
462 return !operator ==(right);
465 bool CDateTime::operator >(const tm& right) const
468 ToFileTime(right, time);
470 return operator >(time);
473 bool CDateTime::operator >=(const tm& right) const
475 return operator >(right) || operator ==(right);
478 bool CDateTime::operator <(const tm& right) const
481 ToFileTime(right, time);
483 return operator <(time);
486 bool CDateTime::operator <=(const tm& right) const
488 return operator <(right) || operator ==(right);
491 bool CDateTime::operator ==(const tm& right) const
494 ToFileTime(right, time);
496 return operator ==(time);
499 bool CDateTime::operator !=(const tm& right) const
501 return !operator ==(right);
504 CDateTime CDateTime::operator +(const CDateTimeSpan& right) const
506 CDateTime left(*this);
508 ULARGE_INTEGER timeLeft;
509 left.ToULargeInt(timeLeft);
511 ULARGE_INTEGER timeRight;
512 right.ToULargeInt(timeRight);
514 timeLeft.QuadPart+=timeRight.QuadPart;
516 left.FromULargeInt(timeLeft);
521 CDateTime CDateTime::operator -(const CDateTimeSpan& right) const
523 CDateTime left(*this);
525 ULARGE_INTEGER timeLeft;
526 left.ToULargeInt(timeLeft);
528 ULARGE_INTEGER timeRight;
529 right.ToULargeInt(timeRight);
531 timeLeft.QuadPart-=timeRight.QuadPart;
533 left.FromULargeInt(timeLeft);
538 const CDateTime& CDateTime::operator +=(const CDateTimeSpan& right)
540 ULARGE_INTEGER timeThis;
541 ToULargeInt(timeThis);
543 ULARGE_INTEGER timeRight;
544 right.ToULargeInt(timeRight);
546 timeThis.QuadPart+=timeRight.QuadPart;
548 FromULargeInt(timeThis);
553 const CDateTime& CDateTime::operator -=(const CDateTimeSpan& right)
555 ULARGE_INTEGER timeThis;
556 ToULargeInt(timeThis);
558 ULARGE_INTEGER timeRight;
559 right.ToULargeInt(timeRight);
561 timeThis.QuadPart-=timeRight.QuadPart;
563 FromULargeInt(timeThis);
568 CDateTimeSpan CDateTime::operator -(const CDateTime& right) const
572 ULARGE_INTEGER timeLeft;
573 left.ToULargeInt(timeLeft);
575 ULARGE_INTEGER timeThis;
576 ToULargeInt(timeThis);
578 ULARGE_INTEGER timeRight;
579 right.ToULargeInt(timeRight);
581 timeLeft.QuadPart=timeThis.QuadPart-timeRight.QuadPart;
583 left.FromULargeInt(timeLeft);
588 CDateTime::operator FILETIME() const
593 void CDateTime::Archive(CArchive& ar)
610 m_state = CDateTime::STATE(state);
615 ToFileTime(st, m_time);
620 void CDateTime::Reset()
622 SetDateTime(1601, 1, 1, 0, 0, 0);
626 void CDateTime::SetValid(bool yesNo)
628 m_state=yesNo ? valid : invalid;
631 bool CDateTime::IsValid() const
633 return m_state==valid;
636 bool CDateTime::ToFileTime(const SYSTEMTIME& time, FILETIME& fileTime) const
638 return SystemTimeToFileTime(&time, &fileTime) == TRUE &&
639 (fileTime.dwLowDateTime > 0 || fileTime.dwHighDateTime > 0);
642 bool CDateTime::ToFileTime(const time_t& time, FILETIME& fileTime) const
644 LONGLONG ll = Int32x32To64(time, 10000000)+0x19DB1DED53E8000LL;
646 fileTime.dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
647 fileTime.dwHighDateTime = (DWORD)(ll >> 32);
652 bool CDateTime::ToFileTime(const tm& time, FILETIME& fileTime) const
655 ZeroMemory(&st, sizeof(SYSTEMTIME));
657 st.wYear=time.tm_year+1900;
658 st.wMonth=time.tm_mon+1;
659 st.wDayOfWeek=time.tm_wday;
660 st.wDay=time.tm_mday;
661 st.wHour=time.tm_hour;
662 st.wMinute=time.tm_min;
663 st.wSecond=time.tm_sec;
665 return SystemTimeToFileTime(&st, &fileTime)==TRUE;
668 void CDateTime::ToULargeInt(ULARGE_INTEGER& time) const
670 time.u.HighPart=m_time.dwHighDateTime;
671 time.u.LowPart=m_time.dwLowDateTime;
674 void CDateTime::FromULargeInt(const ULARGE_INTEGER& time)
676 m_time.dwHighDateTime=time.u.HighPart;
677 m_time.dwLowDateTime=time.u.LowPart;
680 void CDateTime::SetFromDateString(const CStdString &date)
688 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december",NULL};
690 int iDayPos = date.Find("day");
691 int iPos = date.Find(" ");
692 if (iDayPos < iPos && iDayPos > -1)
695 iPos = date.Find(" ",iPos+1);
700 CStdString strMonth = date.Mid(iDayPos,iPos-iDayPos);
701 if (strMonth.IsEmpty()) // assume dbdate format
707 int iPos2 = date.Find(",");
708 CStdString strDay = date.Mid(iPos,iPos2-iPos);
709 CStdString strYear = date.Mid(date.Find(" ",iPos2)+1);
710 while (months[j] && stricmp(strMonth.c_str(),months[j]) != 0)
715 SetDateTime(atol(strYear.c_str()),j+1,atol(strDay.c_str()),0,0,0);
718 int CDateTime::GetDay() const
726 int CDateTime::GetMonth() const
734 int CDateTime::GetYear() const
742 int CDateTime::GetHour() const
750 int CDateTime::GetMinute() const
758 int CDateTime::GetSecond() const
766 int CDateTime::GetDayOfWeek() const
771 return st.wDayOfWeek;
774 int CDateTime::GetMinuteOfDay() const
778 return st.wHour*60+st.wMinute;
781 void CDateTime::SetDateTime(int year, int month, int day, int hour, int minute, int second)
784 ZeroMemory(&st, sizeof(SYSTEMTIME));
793 m_state = ToFileTime(st, m_time) ? valid : invalid;
796 void CDateTime::SetDate(int year, int month, int day)
798 SetDateTime(year, month, day, 0, 0, 0);
801 void CDateTime::SetTime(int hour, int minute, int second)
803 // 01.01.1601 00:00:00 is 0 as filetime
804 SetDateTime(1601, 1, 1, hour, minute, second);
807 void CDateTime::GetAsSystemTime(SYSTEMTIME& time) const
809 FileTimeToSystemTime(&m_time, &time);
812 #define UNIX_BASE_TIME 116444736000000000LL /* nanoseconds since epoch */
813 void CDateTime::GetAsTime(time_t& time) const
816 ll = ((LONGLONG)m_time.dwHighDateTime << 32) + m_time.dwLowDateTime;
817 time=(time_t)((ll - UNIX_BASE_TIME) / 10000000);
820 void CDateTime::GetAsTm(tm& time) const
825 time.tm_year=st.wYear-1900;
826 time.tm_mon=st.wMonth-1;
827 time.tm_wday=st.wDayOfWeek;
828 time.tm_mday=st.wDay;
829 time.tm_hour=st.wHour;
830 time.tm_min=st.wMinute;
831 time.tm_sec=st.wSecond;
836 void CDateTime::GetAsTimeStamp(FILETIME& time) const
838 ::LocalFileTimeToFileTime(&m_time, &time);
841 CStdString CDateTime::GetAsDBDate() const
847 date.Format("%04i-%02i-%02i", st.wYear, st.wMonth, st.wDay);
852 CStdString CDateTime::GetAsDBDateTime() const
858 date.Format("%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
863 CStdString CDateTime::GetAsSaveString() const
869 date.Format("%04i%02i%02i_%02i%02i%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
874 void CDateTime::SetFromUTCDateTime(const CDateTime &dateTime)
876 CDateTime tmp(dateTime);
877 tmp -= GetTimezoneBias();
880 m_state = tmp.m_state;
883 static bool bGotTimezoneBias = false;
885 void CDateTime::ResetTimezoneBias(void)
887 bGotTimezoneBias = false;
890 CDateTimeSpan CDateTime::GetTimezoneBias(void)
892 static CDateTimeSpan timezoneBias;
894 if (!bGotTimezoneBias)
896 bGotTimezoneBias = true;
897 TIME_ZONE_INFORMATION tz;
898 switch(GetTimeZoneInformation(&tz))
900 case TIME_ZONE_ID_DAYLIGHT:
901 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.DaylightBias, 0);
903 case TIME_ZONE_ID_STANDARD:
904 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.StandardBias, 0);
906 case TIME_ZONE_ID_UNKNOWN:
907 timezoneBias = CDateTimeSpan(0, 0, tz.Bias, 0);
915 void CDateTime::SetFromUTCDateTime(const time_t &dateTime)
917 CDateTime tmp(dateTime);
918 SetFromUTCDateTime(tmp);
921 void CDateTime::SetFromW3CDate(const CStdString &dateTime)
923 CStdString date, time, zone;
925 int posT = dateTime.Find("T");
928 date = dateTime.Left(posT);
929 CStdString::size_type posZ = dateTime.find_first_of("+-Z", posT);
930 if(posZ == CStdString::npos)
931 time = dateTime.Mid(posT+1);
934 time = dateTime.Mid(posT+1, posZ-posT-1);
935 zone = dateTime.Mid(posZ);
941 int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
943 if (date.size() >= 4)
944 year = atoi(date.Mid(0,4).c_str());
946 if (date.size() >= 10)
948 month = atoi(date.Mid(5,2).c_str());
949 day = atoi(date.Mid(8,2).c_str());
952 if (time.length() >= 5)
954 hour = atoi(time.Mid(0,2).c_str());
955 min = atoi(time.Mid(3,2).c_str());
958 if (time.length() >= 8)
959 sec = atoi(time.Mid(6,2).c_str());
961 SetDateTime(year, month, day, hour, min, sec);
964 void CDateTime::SetFromDBDateTime(const CStdString &dateTime)
966 // assumes format YYYY-MM-DD HH:MM:SS
967 if (dateTime.size() == 19)
969 int year = atoi(dateTime.Mid(0,4).c_str());
970 int month = atoi(dateTime.Mid(5,2).c_str());
971 int day = atoi(dateTime.Mid(8,2).c_str());
972 int hour = atoi(dateTime.Mid(11,2).c_str());
973 int min = atoi(dateTime.Mid(14,2).c_str());
974 int sec = atoi(dateTime.Mid(17,2).c_str());
975 SetDateTime(year, month, day, hour, min, sec);
979 void CDateTime::SetFromDBDate(const CStdString &date)
982 // YYYY-MM-DD or DD-MM-YYYY
983 int year = 0, month = 0, day = 0;
984 if (date.size() > 2 && (date[2] == '-' || date[2] == '.'))
986 day = atoi(date.Mid(0,2).c_str());
987 month = atoi(date.Mid(3,2).c_str());
988 year = atoi(date.Mid(6,4).c_str());
992 year = atoi(date.Mid(0,4).c_str());
993 month = atoi(date.Mid(5,2).c_str());
994 day = atoi(date.Mid(8,2).c_str());
996 SetDate(year, month, day);
999 void CDateTime::SetFromDBTime(const CStdString &time)
1003 int hour, minute, second;
1005 hour = atoi(time.Mid(0,2).c_str());
1006 minute = atoi(time.Mid(3,2).c_str());
1007 second = atoi(time.Mid(6,2).c_str());
1009 SetTime(hour, minute, second);
1012 void CDateTime::SetFromRFC1123DateTime(const CStdString &dateTime)
1014 CStdString date = dateTime;
1017 if (date.size() != 29)
1020 int day = strtol(date.Mid(5, 2).c_str(), NULL, 10);
1022 CStdString strMonth = date.Mid(8, 3);
1024 for (unsigned int index = 0; index < 12; index++)
1026 if (strMonth.Equals(MONTH_NAMES[index]))
1036 int year = strtol(date.Mid(12, 4).c_str(), NULL, 10);
1037 int hour = strtol(date.Mid(17, 2).c_str(), NULL, 10);
1038 int min = strtol(date.Mid(20, 2).c_str(), NULL, 10);
1039 int sec = strtol(date.Mid(23, 2).c_str(), NULL, 10);
1041 SetDateTime(year, month, day, hour, min, sec);
1044 CStdString CDateTime::GetAsLocalizedTime(const CStdString &format, bool withSeconds) const
1047 const CStdString& strFormat = format.IsEmpty() ? g_langInfo.GetTimeFormat() : format;
1049 SYSTEMTIME dateTime;
1050 GetAsSystemTime(dateTime);
1052 // Prefetch meridiem symbol
1053 const CStdString& strMeridiem=g_langInfo.GetMeridiemSymbol(dateTime.wHour > 11 ? CLangInfo::MERIDIEM_SYMBOL_PM : CLangInfo::MERIDIEM_SYMBOL_AM);
1055 int length=strFormat.GetLength();
1056 for (int i=0; i<length; ++i)
1058 char c=strFormat[i];
1061 // To be able to display a "'" in the string,
1062 // find the last "'" that doesn't follow a "'"
1064 while(((pos=strFormat.Find(c,pos+1))>-1 && pos<strFormat.GetLength()) && strFormat[pos+1]=='\'') {}
1069 // Extract string between ' '
1070 strPart=strFormat.Mid(i+1, pos-i-1);
1075 strPart=strFormat.Mid(i+1, length-i-1);
1079 strPart.Replace("''", "'");
1083 else if (c=='h' || c=='H') // parse hour (H="24 hour clock")
1087 int pos=strFormat.find_first_not_of(c,i+1);
1090 // Get length of the hour mask, eg. HH
1096 // mask ends at the end of the string, extract it
1097 partLength=length-i;
1101 int hour=dateTime.wHour;
1103 { // recalc to 12 hour clock
1105 hour -= (12 * (hour > 12));
1107 hour += (12 * (hour < 1));
1110 // Format hour string with the length of the mask
1113 str.Format("%d", hour);
1115 str.Format("%02d", hour);
1119 else if (c=='m') // parse minutes
1123 int pos=strFormat.find_first_not_of(c,i+1);
1126 // Get length of the minute mask, eg. mm
1132 // mask ends at the end of the string, extract it
1133 partLength=length-i;
1137 // Format minute string with the length of the mask
1140 str.Format("%d", dateTime.wMinute);
1142 str.Format("%02d", dateTime.wMinute);
1146 else if (c=='s') // parse seconds
1150 int pos=strFormat.find_first_not_of(c,i+1);
1153 // Get length of the seconds mask, eg. ss
1159 // mask ends at the end of the string, extract it
1160 partLength=length-i;
1166 // Format seconds string with the length of the mask
1169 str.Format("%d", dateTime.wSecond);
1171 str.Format("%02d", dateTime.wSecond);
1176 strOut.Delete(strOut.GetLength()-1,1);
1178 else if (c=='x') // add meridiem symbol
1180 int pos=strFormat.find_first_not_of(c,i+1);
1183 // Get length of the meridiem mask
1188 // mask ends at the end of the string, extract it
1192 strOut+=strMeridiem;
1194 else // everything else pass to output
1201 CStdString CDateTime::GetAsLocalizedDate(bool longDate/*=false*/, bool withShortNames/*=true*/) const
1203 return GetAsLocalizedDate(g_langInfo.GetDateFormat(longDate), withShortNames);
1206 CStdString CDateTime::GetAsLocalizedDate(const CStdString &strFormat, bool withShortNames/*=true*/) const
1210 SYSTEMTIME dateTime;
1211 GetAsSystemTime(dateTime);
1213 int length=strFormat.GetLength();
1215 for (int i=0; i<length; ++i)
1217 char c=strFormat[i];
1220 // To be able to display a "'" in the string,
1221 // find the last "'" that doesn't follow a "'"
1223 while(((pos=strFormat.Find(c,pos+1))>-1 && pos<strFormat.GetLength()) && strFormat[pos+1]=='\'') {}
1228 // Extract string between ' '
1229 strPart=strFormat.Mid(i+1, pos-i-1);
1234 strPart=strFormat.Mid(i+1, length-i-1);
1237 strPart.Replace("''", "'");
1240 else if (c=='D' || c=='d') // parse days
1244 int pos=strFormat.find_first_not_of(c,i+1);
1247 // Get length of the day mask, eg. DDDD
1253 // mask ends at the end of the string, extract it
1254 partLength=length-i;
1258 // Format string with the length of the mask
1260 if (partLength==1) // single-digit number
1261 str.Format("%d", dateTime.wDay);
1262 else if (partLength==2) // two-digit number
1263 str.Format("%02d", dateTime.wDay);
1264 else // Day of week string
1266 int wday = dateTime.wDayOfWeek;
1267 if (wday < 1 || wday > 7) wday = 7;
1268 str = g_localizeStrings.Get(((withShortNames || c =='d') ? 40 : 10) + wday);
1272 else if (c=='M' || c=='m') // parse month
1276 int pos=strFormat.find_first_not_of(c,i+1);
1279 // Get length of the month mask, eg. MMMM
1285 // mask ends at the end of the string, extract it
1286 partLength=length-i;
1290 // Format string with the length of the mask
1292 if (partLength==1) // single-digit number
1293 str.Format("%d", dateTime.wMonth);
1294 else if (partLength==2) // two-digit number
1295 str.Format("%02d", dateTime.wMonth);
1296 else // Month string
1298 int wmonth = dateTime.wMonth;
1299 if (wmonth < 1 || wmonth > 12) wmonth = 12;
1300 str = g_localizeStrings.Get(((withShortNames || c =='m') ? 50 : 20) + wmonth);
1304 else if (c=='Y' || c =='y') // parse year
1308 int pos=strFormat.find_first_not_of(c,i+1);
1311 // Get length of the year mask, eg. YYYY
1317 // mask ends at the end of the string, extract it
1318 partLength=length-i;
1322 // Format string with the length of the mask
1324 str.Format("%d", dateTime.wYear); // four-digit number
1326 str.Delete(0, 2); // two-digit number
1330 else // everything else pass to output
1337 CStdString CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withSeconds/*=true*/) const
1339 return GetAsLocalizedDate(longDate)+" "+GetAsLocalizedTime("", withSeconds);
1342 CDateTime CDateTime::GetAsUTCDateTime() const
1344 CDateTime time(m_time);
1345 time += GetTimezoneBias();
1349 CStdString CDateTime::GetAsRFC1123DateTime() const
1351 CDateTime time(GetAsUTCDateTime());
1353 int weekDay = time.GetDayOfWeek();
1356 else if (weekDay > 6)
1358 if (weekDay != time.GetDayOfWeek())
1359 CLog::Log(LOGWARNING, "Invalid day of week %d in %s", time.GetDayOfWeek(), time.GetAsDBDateTime().c_str());
1361 int month = time.GetMonth();
1364 else if (month > 12)
1366 if (month != time.GetMonth())
1367 CLog::Log(LOGWARNING, "Invalid month %d in %s", time.GetMonth(), time.GetAsDBDateTime().c_str());
1370 result.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());
1374 int CDateTime::MonthStringToMonthNum(const CStdString& month)
1376 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december"};
1377 const char* abr_months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
1380 for (; i < 12 && month.CompareNoCase(months[i]) != 0 && month.CompareNoCase(abr_months[i]) != 0; i++);