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 void CDateTimeSpan::SetFromPeriod(const CStdString &period)
216 long days = atoi(period.c_str());
217 // find the first non-space and non-number
218 int pos = period.find_first_not_of("0123456789 ", 0);
221 CStdString units = period.Mid(pos, 3);
222 if (units.CompareNoCase("wee") == 0)
224 else if (units.CompareNoCase("mon") == 0)
228 SetDateTimeSpan(days, 0, 0, 0);
231 /////////////////////////////////////////////////
236 CDateTime::CDateTime()
241 CDateTime::CDateTime(const SYSTEMTIME &time)
243 // we store internally as a FILETIME
244 m_state = ToFileTime(time, m_time) ? valid : invalid;
247 CDateTime::CDateTime(const FILETIME &time)
253 CDateTime::CDateTime(const CDateTime& time)
256 m_state=time.m_state;
259 CDateTime::CDateTime(const time_t& time)
261 m_state = ToFileTime(time, m_time) ? valid : invalid;
264 CDateTime::CDateTime(const tm& time)
266 m_state = ToFileTime(time, m_time) ? valid : invalid;
269 CDateTime::CDateTime(int year, int month, int day, int hour, int minute, int second)
271 SetDateTime(year, month, day, hour, minute, second);
274 CDateTime CDateTime::GetCurrentDateTime()
276 // get the current time
280 return CDateTime(time);
283 CDateTime CDateTime::GetUTCDateTime()
285 CDateTime time(GetCurrentDateTime());
286 time += GetTimezoneBias();
290 const CDateTime& CDateTime::operator =(const SYSTEMTIME& right)
292 m_state = ToFileTime(right, m_time) ? valid : invalid;
297 const CDateTime& CDateTime::operator =(const FILETIME& right)
305 const CDateTime& CDateTime::operator =(const time_t& right)
307 m_state = ToFileTime(right, m_time) ? valid : invalid;
312 const CDateTime& CDateTime::operator =(const tm& right)
314 m_state = ToFileTime(right, m_time) ? valid : invalid;
319 bool CDateTime::operator >(const CDateTime& right) const
321 return operator >(right.m_time);
324 bool CDateTime::operator >=(const CDateTime& right) const
326 return operator >(right) || operator ==(right);
329 bool CDateTime::operator <(const CDateTime& right) const
331 return operator <(right.m_time);
334 bool CDateTime::operator <=(const CDateTime& right) const
336 return operator <(right) || operator ==(right);
339 bool CDateTime::operator ==(const CDateTime& right) const
341 return operator ==(right.m_time);
344 bool CDateTime::operator !=(const CDateTime& right) const
346 return !operator ==(right);
349 bool CDateTime::operator >(const FILETIME& right) const
351 return CompareFileTime(&m_time, &right)>0;
354 bool CDateTime::operator >=(const FILETIME& right) const
356 return operator >(right) || operator ==(right);
359 bool CDateTime::operator <(const FILETIME& right) const
361 return CompareFileTime(&m_time, &right)<0;
364 bool CDateTime::operator <=(const FILETIME& right) const
366 return operator <(right) || operator ==(right);
369 bool CDateTime::operator ==(const FILETIME& right) const
371 return CompareFileTime(&m_time, &right)==0;
374 bool CDateTime::operator !=(const FILETIME& right) const
376 return !operator ==(right);
379 bool CDateTime::operator >(const SYSTEMTIME& right) const
382 ToFileTime(right, time);
384 return operator >(time);
387 bool CDateTime::operator >=(const SYSTEMTIME& right) const
389 return operator >(right) || operator ==(right);
392 bool CDateTime::operator <(const SYSTEMTIME& right) const
395 ToFileTime(right, time);
397 return operator <(time);
400 bool CDateTime::operator <=(const SYSTEMTIME& right) const
402 return operator <(right) || operator ==(right);
405 bool CDateTime::operator ==(const SYSTEMTIME& right) const
408 ToFileTime(right, time);
410 return operator ==(time);
413 bool CDateTime::operator !=(const SYSTEMTIME& right) const
415 return !operator ==(right);
418 bool CDateTime::operator >(const time_t& right) const
421 ToFileTime(right, time);
423 return operator >(time);
426 bool CDateTime::operator >=(const time_t& right) const
428 return operator >(right) || operator ==(right);
431 bool CDateTime::operator <(const time_t& right) const
434 ToFileTime(right, time);
436 return operator <(time);
439 bool CDateTime::operator <=(const time_t& right) const
441 return operator <(right) || operator ==(right);
444 bool CDateTime::operator ==(const time_t& right) const
447 ToFileTime(right, time);
449 return operator ==(time);
452 bool CDateTime::operator !=(const time_t& right) const
454 return !operator ==(right);
457 bool CDateTime::operator >(const tm& right) const
460 ToFileTime(right, time);
462 return operator >(time);
465 bool CDateTime::operator >=(const tm& right) const
467 return operator >(right) || operator ==(right);
470 bool CDateTime::operator <(const tm& right) const
473 ToFileTime(right, time);
475 return operator <(time);
478 bool CDateTime::operator <=(const tm& right) const
480 return operator <(right) || operator ==(right);
483 bool CDateTime::operator ==(const tm& right) const
486 ToFileTime(right, time);
488 return operator ==(time);
491 bool CDateTime::operator !=(const tm& right) const
493 return !operator ==(right);
496 CDateTime CDateTime::operator +(const CDateTimeSpan& right) const
498 CDateTime left(*this);
500 ULARGE_INTEGER timeLeft;
501 left.ToULargeInt(timeLeft);
503 ULARGE_INTEGER timeRight;
504 right.ToULargeInt(timeRight);
506 timeLeft.QuadPart+=timeRight.QuadPart;
508 left.FromULargeInt(timeLeft);
513 CDateTime CDateTime::operator -(const CDateTimeSpan& right) const
515 CDateTime left(*this);
517 ULARGE_INTEGER timeLeft;
518 left.ToULargeInt(timeLeft);
520 ULARGE_INTEGER timeRight;
521 right.ToULargeInt(timeRight);
523 timeLeft.QuadPart-=timeRight.QuadPart;
525 left.FromULargeInt(timeLeft);
530 const CDateTime& CDateTime::operator +=(const CDateTimeSpan& right)
532 ULARGE_INTEGER timeThis;
533 ToULargeInt(timeThis);
535 ULARGE_INTEGER timeRight;
536 right.ToULargeInt(timeRight);
538 timeThis.QuadPart+=timeRight.QuadPart;
540 FromULargeInt(timeThis);
545 const CDateTime& CDateTime::operator -=(const CDateTimeSpan& right)
547 ULARGE_INTEGER timeThis;
548 ToULargeInt(timeThis);
550 ULARGE_INTEGER timeRight;
551 right.ToULargeInt(timeRight);
553 timeThis.QuadPart-=timeRight.QuadPart;
555 FromULargeInt(timeThis);
560 CDateTimeSpan CDateTime::operator -(const CDateTime& right) const
564 ULARGE_INTEGER timeLeft;
565 left.ToULargeInt(timeLeft);
567 ULARGE_INTEGER timeThis;
568 ToULargeInt(timeThis);
570 ULARGE_INTEGER timeRight;
571 right.ToULargeInt(timeRight);
573 timeLeft.QuadPart=timeThis.QuadPart-timeRight.QuadPart;
575 left.FromULargeInt(timeLeft);
580 CDateTime::operator FILETIME() const
585 void CDateTime::Archive(CArchive& ar)
602 m_state = CDateTime::STATE(state);
607 ToFileTime(st, m_time);
612 void CDateTime::Reset()
614 SetDateTime(1601, 1, 1, 0, 0, 0);
618 void CDateTime::SetValid(bool yesNo)
620 m_state=yesNo ? valid : invalid;
623 bool CDateTime::IsValid() const
625 return m_state==valid;
628 bool CDateTime::ToFileTime(const SYSTEMTIME& time, FILETIME& fileTime) const
630 return SystemTimeToFileTime(&time, &fileTime) == TRUE &&
631 (fileTime.dwLowDateTime > 0 || fileTime.dwHighDateTime > 0);
634 bool CDateTime::ToFileTime(const time_t& time, FILETIME& fileTime) const
636 LONGLONG ll = Int32x32To64(time, 10000000)+0x19DB1DED53E8000LL;
638 fileTime.dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
639 fileTime.dwHighDateTime = (DWORD)(ll >> 32);
644 bool CDateTime::ToFileTime(const tm& time, FILETIME& fileTime) const
647 ZeroMemory(&st, sizeof(SYSTEMTIME));
649 st.wYear=time.tm_year+1900;
650 st.wMonth=time.tm_mon+1;
651 st.wDayOfWeek=time.tm_wday;
652 st.wDay=time.tm_mday;
653 st.wHour=time.tm_hour;
654 st.wMinute=time.tm_min;
655 st.wSecond=time.tm_sec;
657 return SystemTimeToFileTime(&st, &fileTime)==TRUE;
660 void CDateTime::ToULargeInt(ULARGE_INTEGER& time) const
662 time.u.HighPart=m_time.dwHighDateTime;
663 time.u.LowPart=m_time.dwLowDateTime;
666 void CDateTime::FromULargeInt(const ULARGE_INTEGER& time)
668 m_time.dwHighDateTime=time.u.HighPart;
669 m_time.dwLowDateTime=time.u.LowPart;
672 void CDateTime::SetFromDateString(const CStdString &date)
680 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december",NULL};
682 int iDayPos = date.Find("day");
683 int iPos = date.Find(" ");
684 if (iDayPos < iPos && iDayPos > -1)
687 iPos = date.Find(" ",iPos+1);
692 CStdString strMonth = date.Mid(iDayPos,iPos-iDayPos);
693 if (strMonth.IsEmpty()) // assume dbdate format
699 int iPos2 = date.Find(",");
700 CStdString strDay = date.Mid(iPos,iPos2-iPos);
701 CStdString strYear = date.Mid(date.Find(" ",iPos2)+1);
702 while (months[j] && stricmp(strMonth.c_str(),months[j]) != 0)
707 SetDateTime(atol(strYear.c_str()),j+1,atol(strDay.c_str()),0,0,0);
710 int CDateTime::GetDay() const
718 int CDateTime::GetMonth() const
726 int CDateTime::GetYear() const
734 int CDateTime::GetHour() const
742 int CDateTime::GetMinute() const
750 int CDateTime::GetSecond() const
758 int CDateTime::GetDayOfWeek() const
763 return st.wDayOfWeek;
766 int CDateTime::GetMinuteOfDay() const
770 return st.wHour*60+st.wMinute;
773 void CDateTime::SetDateTime(int year, int month, int day, int hour, int minute, int second)
776 ZeroMemory(&st, sizeof(SYSTEMTIME));
785 m_state = ToFileTime(st, m_time) ? valid : invalid;
788 void CDateTime::SetDate(int year, int month, int day)
790 SetDateTime(year, month, day, 0, 0, 0);
793 void CDateTime::SetTime(int hour, int minute, int second)
795 // 01.01.1601 00:00:00 is 0 as filetime
796 SetDateTime(1601, 1, 1, hour, minute, second);
799 void CDateTime::GetAsSystemTime(SYSTEMTIME& time) const
801 FileTimeToSystemTime(&m_time, &time);
804 #define UNIX_BASE_TIME 116444736000000000LL /* nanoseconds since epoch */
805 void CDateTime::GetAsTime(time_t& time) const
808 ll = ((LONGLONG)m_time.dwHighDateTime << 32) + m_time.dwLowDateTime;
809 time=(time_t)((ll - UNIX_BASE_TIME) / 10000000);
812 void CDateTime::GetAsTm(tm& time) const
817 time.tm_year=st.wYear-1900;
818 time.tm_mon=st.wMonth-1;
819 time.tm_wday=st.wDayOfWeek;
820 time.tm_mday=st.wDay;
821 time.tm_hour=st.wHour;
822 time.tm_min=st.wMinute;
823 time.tm_sec=st.wSecond;
828 void CDateTime::GetAsTimeStamp(FILETIME& time) const
830 ::LocalFileTimeToFileTime(&m_time, &time);
833 CStdString CDateTime::GetAsDBDate() const
839 date.Format("%04i-%02i-%02i", st.wYear, st.wMonth, st.wDay);
844 CStdString CDateTime::GetAsDBDateTime() const
850 date.Format("%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
855 CStdString CDateTime::GetAsSaveString() const
861 date.Format("%04i%02i%02i_%02i%02i%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
866 void CDateTime::SetFromUTCDateTime(const CDateTime &dateTime)
868 CDateTime tmp(dateTime);
869 tmp -= GetTimezoneBias();
872 m_state = tmp.m_state;
875 static bool bGotTimezoneBias = false;
877 void CDateTime::ResetTimezoneBias(void)
879 bGotTimezoneBias = false;
882 CDateTimeSpan CDateTime::GetTimezoneBias(void)
884 static CDateTimeSpan timezoneBias;
886 if (!bGotTimezoneBias)
888 bGotTimezoneBias = true;
889 TIME_ZONE_INFORMATION tz;
890 switch(GetTimeZoneInformation(&tz))
892 case TIME_ZONE_ID_DAYLIGHT:
893 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.DaylightBias, 0);
895 case TIME_ZONE_ID_STANDARD:
896 timezoneBias = CDateTimeSpan(0, 0, tz.Bias + tz.StandardBias, 0);
898 case TIME_ZONE_ID_UNKNOWN:
899 timezoneBias = CDateTimeSpan(0, 0, tz.Bias, 0);
907 void CDateTime::SetFromUTCDateTime(const time_t &dateTime)
909 CDateTime tmp(dateTime);
910 SetFromUTCDateTime(tmp);
913 void CDateTime::SetFromW3CDate(const CStdString &dateTime)
915 CStdString date, time, zone;
917 int posT = dateTime.Find("T");
920 date = dateTime.Left(posT);
921 CStdString::size_type posZ = dateTime.find_first_of("+-Z", posT);
922 if(posZ == CStdString::npos)
923 time = dateTime.Mid(posT+1);
926 time = dateTime.Mid(posT+1, posZ-posT-1);
927 zone = dateTime.Mid(posZ);
933 int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
935 if (date.size() >= 4)
936 year = atoi(date.Mid(0,4).c_str());
938 if (date.size() >= 10)
940 month = atoi(date.Mid(5,2).c_str());
941 day = atoi(date.Mid(8,2).c_str());
944 if (time.length() >= 5)
946 hour = atoi(time.Mid(0,2).c_str());
947 min = atoi(time.Mid(3,2).c_str());
950 if (time.length() >= 8)
951 sec = atoi(time.Mid(6,2).c_str());
953 SetDateTime(year, month, day, hour, min, sec);
956 void CDateTime::SetFromDBDateTime(const CStdString &dateTime)
958 // assumes format YYYY-MM-DD HH:MM:SS
959 if (dateTime.size() == 19)
961 int year = atoi(dateTime.Mid(0,4).c_str());
962 int month = atoi(dateTime.Mid(5,2).c_str());
963 int day = atoi(dateTime.Mid(8,2).c_str());
964 int hour = atoi(dateTime.Mid(11,2).c_str());
965 int min = atoi(dateTime.Mid(14,2).c_str());
966 int sec = atoi(dateTime.Mid(17,2).c_str());
967 SetDateTime(year, month, day, hour, min, sec);
971 void CDateTime::SetFromDBDate(const CStdString &date)
974 // YYYY-MM-DD or DD-MM-YYYY
975 int year = 0, month = 0, day = 0;
976 if (date.size() > 2 && (date[2] == '-' || date[2] == '.'))
978 day = atoi(date.Mid(0,2).c_str());
979 month = atoi(date.Mid(3,2).c_str());
980 year = atoi(date.Mid(6,4).c_str());
984 year = atoi(date.Mid(0,4).c_str());
985 month = atoi(date.Mid(5,2).c_str());
986 day = atoi(date.Mid(8,2).c_str());
988 SetDate(year, month, day);
991 void CDateTime::SetFromDBTime(const CStdString &time)
995 int hour, minute, second;
997 hour = atoi(time.Mid(0,2).c_str());
998 minute = atoi(time.Mid(3,2).c_str());
999 second = atoi(time.Mid(6,2).c_str());
1001 SetTime(hour, minute, second);
1004 void CDateTime::SetFromRFC1123DateTime(const CStdString &dateTime)
1006 CStdString date = dateTime;
1009 if (date.size() != 29)
1012 int day = strtol(date.Mid(5, 2).c_str(), NULL, 10);
1014 CStdString strMonth = date.Mid(8, 3);
1016 for (unsigned int index = 0; index < 12; index++)
1018 if (strMonth.Equals(MONTH_NAMES[index]))
1028 int year = strtol(date.Mid(12, 4).c_str(), NULL, 10);
1029 int hour = strtol(date.Mid(17, 2).c_str(), NULL, 10);
1030 int min = strtol(date.Mid(20, 2).c_str(), NULL, 10);
1031 int sec = strtol(date.Mid(23, 2).c_str(), NULL, 10);
1033 SetDateTime(year, month, day, hour, min, sec);
1036 CStdString CDateTime::GetAsLocalizedTime(const CStdString &format, bool withSeconds) const
1039 const CStdString& strFormat = format.IsEmpty() ? g_langInfo.GetTimeFormat() : format;
1041 SYSTEMTIME dateTime;
1042 GetAsSystemTime(dateTime);
1044 // Prefetch meridiem symbol
1045 const CStdString& strMeridiem=g_langInfo.GetMeridiemSymbol(dateTime.wHour > 11 ? CLangInfo::MERIDIEM_SYMBOL_PM : CLangInfo::MERIDIEM_SYMBOL_AM);
1047 int length=strFormat.GetLength();
1048 for (int i=0; i<length; ++i)
1050 char c=strFormat[i];
1053 // To be able to display a "'" in the string,
1054 // find the last "'" that doesn't follow a "'"
1056 while(((pos=strFormat.Find(c,pos+1))>-1 && pos<strFormat.GetLength()) && strFormat[pos+1]=='\'') {}
1061 // Extract string between ' '
1062 strPart=strFormat.Mid(i+1, pos-i-1);
1067 strPart=strFormat.Mid(i+1, length-i-1);
1071 strPart.Replace("''", "'");
1075 else if (c=='h' || c=='H') // parse hour (H="24 hour clock")
1079 int pos=strFormat.find_first_not_of(c,i+1);
1082 // Get length of the hour mask, eg. HH
1088 // mask ends at the end of the string, extract it
1089 partLength=length-i;
1093 int hour=dateTime.wHour;
1095 { // recalc to 12 hour clock
1097 hour -= (12 * (hour > 12));
1099 hour += (12 * (hour < 1));
1102 // Format hour string with the length of the mask
1105 str.Format("%d", hour);
1107 str.Format("%02d", hour);
1111 else if (c=='m') // parse minutes
1115 int pos=strFormat.find_first_not_of(c,i+1);
1118 // Get length of the minute mask, eg. mm
1124 // mask ends at the end of the string, extract it
1125 partLength=length-i;
1129 // Format minute string with the length of the mask
1132 str.Format("%d", dateTime.wMinute);
1134 str.Format("%02d", dateTime.wMinute);
1138 else if (c=='s') // parse seconds
1142 int pos=strFormat.find_first_not_of(c,i+1);
1145 // Get length of the seconds mask, eg. ss
1151 // mask ends at the end of the string, extract it
1152 partLength=length-i;
1158 // Format seconds string with the length of the mask
1161 str.Format("%d", dateTime.wSecond);
1163 str.Format("%02d", dateTime.wSecond);
1168 strOut.Delete(strOut.GetLength()-1,1);
1170 else if (c=='x') // add meridiem symbol
1172 int pos=strFormat.find_first_not_of(c,i+1);
1175 // Get length of the meridiem mask
1180 // mask ends at the end of the string, extract it
1184 strOut+=strMeridiem;
1186 else // everything else pass to output
1193 CStdString CDateTime::GetAsLocalizedDate(bool longDate/*=false*/, bool withShortNames/*=true*/) const
1195 return GetAsLocalizedDate(g_langInfo.GetDateFormat(longDate), withShortNames);
1198 CStdString CDateTime::GetAsLocalizedDate(const CStdString &strFormat, bool withShortNames/*=true*/) const
1202 SYSTEMTIME dateTime;
1203 GetAsSystemTime(dateTime);
1205 int length=strFormat.GetLength();
1207 for (int i=0; i<length; ++i)
1209 char c=strFormat[i];
1212 // To be able to display a "'" in the string,
1213 // find the last "'" that doesn't follow a "'"
1215 while(((pos=strFormat.Find(c,pos+1))>-1 && pos<strFormat.GetLength()) && strFormat[pos+1]=='\'') {}
1220 // Extract string between ' '
1221 strPart=strFormat.Mid(i+1, pos-i-1);
1226 strPart=strFormat.Mid(i+1, length-i-1);
1229 strPart.Replace("''", "'");
1232 else if (c=='D' || c=='d') // parse days
1236 int pos=strFormat.find_first_not_of(c,i+1);
1239 // Get length of the day mask, eg. DDDD
1245 // mask ends at the end of the string, extract it
1246 partLength=length-i;
1250 // Format string with the length of the mask
1252 if (partLength==1) // single-digit number
1253 str.Format("%d", dateTime.wDay);
1254 else if (partLength==2) // two-digit number
1255 str.Format("%02d", dateTime.wDay);
1256 else // Day of week string
1258 int wday = dateTime.wDayOfWeek;
1259 if (wday < 1 || wday > 7) wday = 7;
1260 str = g_localizeStrings.Get(((withShortNames || c =='d') ? 40 : 10) + wday);
1264 else if (c=='M' || c=='m') // parse month
1268 int pos=strFormat.find_first_not_of(c,i+1);
1271 // Get length of the month mask, eg. MMMM
1277 // mask ends at the end of the string, extract it
1278 partLength=length-i;
1282 // Format string with the length of the mask
1284 if (partLength==1) // single-digit number
1285 str.Format("%d", dateTime.wMonth);
1286 else if (partLength==2) // two-digit number
1287 str.Format("%02d", dateTime.wMonth);
1288 else // Month string
1290 int wmonth = dateTime.wMonth;
1291 if (wmonth < 1 || wmonth > 12) wmonth = 12;
1292 str = g_localizeStrings.Get(((withShortNames || c =='m') ? 50 : 20) + wmonth);
1296 else if (c=='Y' || c =='y') // parse year
1300 int pos=strFormat.find_first_not_of(c,i+1);
1303 // Get length of the year mask, eg. YYYY
1309 // mask ends at the end of the string, extract it
1310 partLength=length-i;
1314 // Format string with the length of the mask
1316 str.Format("%d", dateTime.wYear); // four-digit number
1318 str.Delete(0, 2); // two-digit number
1322 else // everything else pass to output
1329 CStdString CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withSeconds/*=true*/) const
1331 return GetAsLocalizedDate(longDate)+" "+GetAsLocalizedTime("", withSeconds);
1334 CDateTime CDateTime::GetAsUTCDateTime() const
1336 CDateTime time(m_time);
1337 time += GetTimezoneBias();
1341 CStdString CDateTime::GetAsRFC1123DateTime() const
1343 CDateTime time(GetAsUTCDateTime());
1345 int weekDay = time.GetDayOfWeek();
1348 else if (weekDay > 6)
1350 if (weekDay != time.GetDayOfWeek())
1351 CLog::Log(LOGWARNING, "Invalid day of week %d in %s", time.GetDayOfWeek(), time.GetAsDBDateTime().c_str());
1353 int month = time.GetMonth();
1356 else if (month > 12)
1358 if (month != time.GetMonth())
1359 CLog::Log(LOGWARNING, "Invalid month %d in %s", time.GetMonth(), time.GetAsDBDateTime().c_str());
1362 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());
1366 int CDateTime::MonthStringToMonthNum(const CStdString& month)
1368 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december"};
1369 const char* abr_months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
1372 for (; i < 12 && month.CompareNoCase(months[i]) != 0 && month.CompareNoCase(abr_months[i]) != 0; i++);