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 #define SECONDS_PER_DAY 86400UL
28 #define SECONDS_PER_HOUR 3600UL
29 #define SECONDS_PER_MINUTE 60UL
30 #define SECONDS_TO_FILETIME 10000000UL
32 static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
33 static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
35 /////////////////////////////////////////////////
40 CDateTimeSpan::CDateTimeSpan()
42 m_timeSpan.dwHighDateTime=0;
43 m_timeSpan.dwLowDateTime=0;
46 CDateTimeSpan::CDateTimeSpan(const CDateTimeSpan& span)
48 m_timeSpan.dwHighDateTime=span.m_timeSpan.dwHighDateTime;
49 m_timeSpan.dwLowDateTime=span.m_timeSpan.dwLowDateTime;
52 CDateTimeSpan::CDateTimeSpan(int day, int hour, int minute, int second)
54 SetDateTimeSpan(day, hour, minute, second);
57 bool CDateTimeSpan::operator >(const CDateTimeSpan& right) const
59 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)>0;
62 bool CDateTimeSpan::operator >=(const CDateTimeSpan& right) const
64 return operator >(right) || operator ==(right);
67 bool CDateTimeSpan::operator <(const CDateTimeSpan& right) const
69 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)<0;
72 bool CDateTimeSpan::operator <=(const CDateTimeSpan& right) const
74 return operator <(right) || operator ==(right);
77 bool CDateTimeSpan::operator ==(const CDateTimeSpan& right) const
79 return CompareFileTime(&m_timeSpan, &right.m_timeSpan)==0;
82 bool CDateTimeSpan::operator !=(const CDateTimeSpan& right) const
84 return !operator ==(right);
87 CDateTimeSpan CDateTimeSpan::operator +(const CDateTimeSpan& right) const
89 CDateTimeSpan left(*this);
91 ULARGE_INTEGER timeLeft;
92 left.ToULargeInt(timeLeft);
94 ULARGE_INTEGER timeRight;
95 right.ToULargeInt(timeRight);
97 timeLeft.QuadPart+=timeRight.QuadPart;
99 left.FromULargeInt(timeLeft);
104 CDateTimeSpan CDateTimeSpan::operator -(const CDateTimeSpan& right) const
106 CDateTimeSpan left(*this);
108 ULARGE_INTEGER timeLeft;
109 left.ToULargeInt(timeLeft);
111 ULARGE_INTEGER timeRight;
112 right.ToULargeInt(timeRight);
114 timeLeft.QuadPart-=timeRight.QuadPart;
116 left.FromULargeInt(timeLeft);
121 const CDateTimeSpan& CDateTimeSpan::operator +=(const CDateTimeSpan& right)
123 ULARGE_INTEGER timeThis;
124 ToULargeInt(timeThis);
126 ULARGE_INTEGER timeRight;
127 right.ToULargeInt(timeRight);
129 timeThis.QuadPart+=timeRight.QuadPart;
131 FromULargeInt(timeThis);
136 const CDateTimeSpan& CDateTimeSpan::operator -=(const CDateTimeSpan& right)
138 ULARGE_INTEGER timeThis;
139 ToULargeInt(timeThis);
141 ULARGE_INTEGER timeRight;
142 right.ToULargeInt(timeRight);
144 timeThis.QuadPart-=timeRight.QuadPart;
146 FromULargeInt(timeThis);
151 void CDateTimeSpan::ToULargeInt(ULARGE_INTEGER& time) const
153 time.u.HighPart=m_timeSpan.dwHighDateTime;
154 time.u.LowPart=m_timeSpan.dwLowDateTime;
157 void CDateTimeSpan::FromULargeInt(const ULARGE_INTEGER& time)
159 m_timeSpan.dwHighDateTime=time.u.HighPart;
160 m_timeSpan.dwLowDateTime=time.u.LowPart;
163 void CDateTimeSpan::SetDateTimeSpan(int day, int hour, int minute, int second)
168 time.QuadPart=(LONGLONG)day*SECONDS_PER_DAY*SECONDS_TO_FILETIME;
169 time.QuadPart+=(LONGLONG)hour*SECONDS_PER_HOUR*SECONDS_TO_FILETIME;
170 time.QuadPart+=(LONGLONG)minute*SECONDS_PER_MINUTE*SECONDS_TO_FILETIME;
171 time.QuadPart+=(LONGLONG)second*SECONDS_TO_FILETIME;
176 void CDateTimeSpan::SetFromTimeString(const CStdString& time) // hh:mm
178 int hour = atoi(time.substr(0, 2).c_str());
179 int minutes = atoi(time.substr(3, 2).c_str());
180 SetDateTimeSpan(0,hour,minutes,0);
183 int CDateTimeSpan::GetDays() const
188 return (int)(time.QuadPart/SECONDS_TO_FILETIME)/SECONDS_PER_DAY;
191 int CDateTimeSpan::GetHours() const
196 return (int)((time.QuadPart/SECONDS_TO_FILETIME)%SECONDS_PER_DAY)/SECONDS_PER_HOUR;
199 int CDateTimeSpan::GetMinutes() const
204 return (int)((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)/SECONDS_PER_MINUTE;
207 int CDateTimeSpan::GetSeconds() const
212 return (int)(((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)%SECONDS_PER_MINUTE)%SECONDS_PER_MINUTE;
215 int CDateTimeSpan::GetSecondsTotal() const
220 return (int)(time.QuadPart/SECONDS_TO_FILETIME);
223 void CDateTimeSpan::SetFromPeriod(const CStdString &period)
225 long days = atoi(period.c_str());
226 // find the first non-space and non-number
227 size_t pos = period.find_first_not_of("0123456789 ", 0);
228 if (pos != std::string::npos)
230 CStdString units = period.substr(pos, 3);
231 if (units.CompareNoCase("wee") == 0)
233 else if (units.CompareNoCase("mon") == 0)
237 SetDateTimeSpan(days, 0, 0, 0);
240 /////////////////////////////////////////////////
245 CDateTime::CDateTime()
250 CDateTime::CDateTime(const SYSTEMTIME &time)
252 // we store internally as a FILETIME
253 m_state = ToFileTime(time, m_time) ? valid : invalid;
256 CDateTime::CDateTime(const FILETIME &time)
262 CDateTime::CDateTime(const CDateTime& time)
265 m_state=time.m_state;
268 CDateTime::CDateTime(const time_t& time)
270 m_state = ToFileTime(time, m_time) ? valid : invalid;
273 CDateTime::CDateTime(const tm& time)
275 m_state = ToFileTime(time, m_time) ? valid : invalid;
278 CDateTime::CDateTime(int year, int month, int day, int hour, int minute, int second)
280 SetDateTime(year, month, day, hour, minute, second);
283 CDateTime CDateTime::GetCurrentDateTime()
285 // get the current time
289 return CDateTime(time);
292 CDateTime CDateTime::GetUTCDateTime()
294 CDateTime time(GetCurrentDateTime());
295 time += GetTimezoneBias();
299 const CDateTime& CDateTime::operator =(const SYSTEMTIME& right)
301 m_state = ToFileTime(right, m_time) ? valid : invalid;
306 const CDateTime& CDateTime::operator =(const FILETIME& right)
314 const CDateTime& CDateTime::operator =(const time_t& right)
316 m_state = ToFileTime(right, m_time) ? valid : invalid;
321 const CDateTime& CDateTime::operator =(const tm& right)
323 m_state = ToFileTime(right, m_time) ? valid : invalid;
328 bool CDateTime::operator >(const CDateTime& right) const
330 return operator >(right.m_time);
333 bool CDateTime::operator >=(const CDateTime& right) const
335 return operator >(right) || operator ==(right);
338 bool CDateTime::operator <(const CDateTime& right) const
340 return operator <(right.m_time);
343 bool CDateTime::operator <=(const CDateTime& right) const
345 return operator <(right) || operator ==(right);
348 bool CDateTime::operator ==(const CDateTime& right) const
350 return operator ==(right.m_time);
353 bool CDateTime::operator !=(const CDateTime& right) const
355 return !operator ==(right);
358 bool CDateTime::operator >(const FILETIME& right) const
360 return CompareFileTime(&m_time, &right)>0;
363 bool CDateTime::operator >=(const FILETIME& right) const
365 return operator >(right) || operator ==(right);
368 bool CDateTime::operator <(const FILETIME& right) const
370 return CompareFileTime(&m_time, &right)<0;
373 bool CDateTime::operator <=(const FILETIME& right) const
375 return operator <(right) || operator ==(right);
378 bool CDateTime::operator ==(const FILETIME& right) const
380 return CompareFileTime(&m_time, &right)==0;
383 bool CDateTime::operator !=(const FILETIME& right) const
385 return !operator ==(right);
388 bool CDateTime::operator >(const SYSTEMTIME& right) const
391 ToFileTime(right, time);
393 return operator >(time);
396 bool CDateTime::operator >=(const SYSTEMTIME& right) const
398 return operator >(right) || operator ==(right);
401 bool CDateTime::operator <(const SYSTEMTIME& right) const
404 ToFileTime(right, time);
406 return operator <(time);
409 bool CDateTime::operator <=(const SYSTEMTIME& right) const
411 return operator <(right) || operator ==(right);
414 bool CDateTime::operator ==(const SYSTEMTIME& right) const
417 ToFileTime(right, time);
419 return operator ==(time);
422 bool CDateTime::operator !=(const SYSTEMTIME& right) const
424 return !operator ==(right);
427 bool CDateTime::operator >(const time_t& right) const
430 ToFileTime(right, time);
432 return operator >(time);
435 bool CDateTime::operator >=(const time_t& right) const
437 return operator >(right) || operator ==(right);
440 bool CDateTime::operator <(const time_t& right) const
443 ToFileTime(right, time);
445 return operator <(time);
448 bool CDateTime::operator <=(const time_t& right) const
450 return operator <(right) || operator ==(right);
453 bool CDateTime::operator ==(const time_t& right) const
456 ToFileTime(right, time);
458 return operator ==(time);
461 bool CDateTime::operator !=(const time_t& right) const
463 return !operator ==(right);
466 bool CDateTime::operator >(const tm& right) const
469 ToFileTime(right, time);
471 return operator >(time);
474 bool CDateTime::operator >=(const tm& right) const
476 return operator >(right) || operator ==(right);
479 bool CDateTime::operator <(const tm& right) const
482 ToFileTime(right, time);
484 return operator <(time);
487 bool CDateTime::operator <=(const tm& right) const
489 return operator <(right) || operator ==(right);
492 bool CDateTime::operator ==(const tm& right) const
495 ToFileTime(right, time);
497 return operator ==(time);
500 bool CDateTime::operator !=(const tm& right) const
502 return !operator ==(right);
505 CDateTime CDateTime::operator +(const CDateTimeSpan& right) const
507 CDateTime left(*this);
509 ULARGE_INTEGER timeLeft;
510 left.ToULargeInt(timeLeft);
512 ULARGE_INTEGER timeRight;
513 right.ToULargeInt(timeRight);
515 timeLeft.QuadPart+=timeRight.QuadPart;
517 left.FromULargeInt(timeLeft);
522 CDateTime CDateTime::operator -(const CDateTimeSpan& right) const
524 CDateTime left(*this);
526 ULARGE_INTEGER timeLeft;
527 left.ToULargeInt(timeLeft);
529 ULARGE_INTEGER timeRight;
530 right.ToULargeInt(timeRight);
532 timeLeft.QuadPart-=timeRight.QuadPart;
534 left.FromULargeInt(timeLeft);
539 const CDateTime& CDateTime::operator +=(const CDateTimeSpan& right)
541 ULARGE_INTEGER timeThis;
542 ToULargeInt(timeThis);
544 ULARGE_INTEGER timeRight;
545 right.ToULargeInt(timeRight);
547 timeThis.QuadPart+=timeRight.QuadPart;
549 FromULargeInt(timeThis);
554 const CDateTime& CDateTime::operator -=(const CDateTimeSpan& right)
556 ULARGE_INTEGER timeThis;
557 ToULargeInt(timeThis);
559 ULARGE_INTEGER timeRight;
560 right.ToULargeInt(timeRight);
562 timeThis.QuadPart-=timeRight.QuadPart;
564 FromULargeInt(timeThis);
569 CDateTimeSpan CDateTime::operator -(const CDateTime& right) const
573 ULARGE_INTEGER timeLeft;
574 left.ToULargeInt(timeLeft);
576 ULARGE_INTEGER timeThis;
577 ToULargeInt(timeThis);
579 ULARGE_INTEGER timeRight;
580 right.ToULargeInt(timeRight);
582 timeLeft.QuadPart=timeThis.QuadPart-timeRight.QuadPart;
584 left.FromULargeInt(timeLeft);
589 CDateTime::operator FILETIME() const
594 void CDateTime::Archive(CArchive& ar)
611 m_state = CDateTime::STATE(state);
616 ToFileTime(st, m_time);
621 void CDateTime::Reset()
623 SetDateTime(1601, 1, 1, 0, 0, 0);
627 void CDateTime::SetValid(bool yesNo)
629 m_state=yesNo ? valid : invalid;
632 bool CDateTime::IsValid() const
634 return m_state==valid;
637 bool CDateTime::ToFileTime(const SYSTEMTIME& time, FILETIME& fileTime) const
639 return SystemTimeToFileTime(&time, &fileTime) == TRUE &&
640 (fileTime.dwLowDateTime > 0 || fileTime.dwHighDateTime > 0);
643 bool CDateTime::ToFileTime(const time_t& time, FILETIME& fileTime) const
645 LONGLONG ll = Int32x32To64(time, 10000000)+0x19DB1DED53E8000LL;
647 fileTime.dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
648 fileTime.dwHighDateTime = (DWORD)(ll >> 32);
653 bool CDateTime::ToFileTime(const tm& time, FILETIME& fileTime) const
656 ZeroMemory(&st, sizeof(SYSTEMTIME));
658 st.wYear=time.tm_year+1900;
659 st.wMonth=time.tm_mon+1;
660 st.wDayOfWeek=time.tm_wday;
661 st.wDay=time.tm_mday;
662 st.wHour=time.tm_hour;
663 st.wMinute=time.tm_min;
664 st.wSecond=time.tm_sec;
666 return SystemTimeToFileTime(&st, &fileTime)==TRUE;
669 void CDateTime::ToULargeInt(ULARGE_INTEGER& time) const
671 time.u.HighPart=m_time.dwHighDateTime;
672 time.u.LowPart=m_time.dwLowDateTime;
675 void CDateTime::FromULargeInt(const ULARGE_INTEGER& time)
677 m_time.dwHighDateTime=time.u.HighPart;
678 m_time.dwLowDateTime=time.u.LowPart;
681 void CDateTime::SetFromDateString(const CStdString &date)
689 const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december",NULL};
691 size_t iDayPos = date.find("day");
692 size_t iPos = date.find(" ");
693 if (iDayPos < iPos && iDayPos != std::string::npos)
696 iPos = date.find(" ", iPos+1);
701 CStdString strMonth = date.substr(iDayPos, iPos - iDayPos);
702 if (strMonth.empty()) // assume dbdate format
708 size_t iPos2 = date.find(",");
709 CStdString strDay = date.substr(iPos, iPos2-iPos);
710 CStdString strYear = date.substr(date.find(" ", iPos2) + 1);
711 while (months[j] && stricmp(strMonth.c_str(),months[j]) != 0)
716 SetDateTime(atol(strYear.c_str()),j+1,atol(strDay.c_str()),0,0,0);
719 int CDateTime::GetDay() const
727 int CDateTime::GetMonth() const
735 int CDateTime::GetYear() const
743 int CDateTime::GetHour() const
751 int CDateTime::GetMinute() const
759 int CDateTime::GetSecond() const
767 int CDateTime::GetDayOfWeek() const
772 return st.wDayOfWeek;
775 int CDateTime::GetMinuteOfDay() const
779 return st.wHour*60+st.wMinute;
782 void CDateTime::SetDateTime(int year, int month, int day, int hour, int minute, int second)
785 ZeroMemory(&st, sizeof(SYSTEMTIME));
794 m_state = ToFileTime(st, m_time) ? valid : invalid;
797 void CDateTime::SetDate(int year, int month, int day)
799 SetDateTime(year, month, day, 0, 0, 0);
802 void CDateTime::SetTime(int hour, int minute, int second)
804 // 01.01.1601 00:00:00 is 0 as filetime
805 SetDateTime(1601, 1, 1, hour, minute, second);
808 void CDateTime::GetAsSystemTime(SYSTEMTIME& time) const
810 FileTimeToSystemTime(&m_time, &time);
813 #define UNIX_BASE_TIME 116444736000000000LL /* nanoseconds since epoch */
814 void CDateTime::GetAsTime(time_t& time) const
817 ll = ((LONGLONG)m_time.dwHighDateTime << 32) + m_time.dwLowDateTime;
818 time=(time_t)((ll - UNIX_BASE_TIME) / 10000000);
821 void CDateTime::GetAsTm(tm& time) const
826 time.tm_year=st.wYear-1900;
827 time.tm_mon=st.wMonth-1;
828 time.tm_wday=st.wDayOfWeek;
829 time.tm_mday=st.wDay;
830 time.tm_hour=st.wHour;
831 time.tm_min=st.wMinute;
832 time.tm_sec=st.wSecond;
837 void CDateTime::GetAsTimeStamp(FILETIME& time) const
839 ::LocalFileTimeToFileTime(&m_time, &time);
842 CStdString CDateTime::GetAsDBDate() const
847 return StringUtils::Format("%04i-%02i-%02i", st.wYear, st.wMonth, st.wDay);
850 CStdString CDateTime::GetAsDBDateTime() const
855 return StringUtils::Format("%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
858 CStdString CDateTime::GetAsSaveString() const
863 return StringUtils::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 size_t posT = dateTime.find("T");
918 if(posT != std::string::npos)
920 date = dateTime.substr(0, posT);
921 CStdString::size_type posZ = dateTime.find_first_of("+-Z", posT);
922 if(posZ == CStdString::npos)
923 time = dateTime.substr(posT + 1);
926 time = dateTime.substr(posT + 1, posZ - posT - 1);
927 zone = dateTime.substr(posZ);
933 int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
935 if (date.size() >= 4)
936 year = atoi(date.substr(0, 4).c_str());
938 if (date.size() >= 10)
940 month = atoi(date.substr(5, 2).c_str());
941 day = atoi(date.substr(8, 2).c_str());
944 if (time.length() >= 5)
946 hour = atoi(time.substr(0, 2).c_str());
947 min = atoi(time.substr(3, 2).c_str());
950 if (time.length() >= 8)
951 sec = atoi(time.substr(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.substr(0, 4).c_str());
962 int month = atoi(dateTime.substr(5, 2).c_str());
963 int day = atoi(dateTime.substr(8, 2).c_str());
964 int hour = atoi(dateTime.substr(11, 2).c_str());
965 int min = atoi(dateTime.substr(14, 2).c_str());
966 int sec = atoi(dateTime.substr(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.substr(0, 2).c_str());
979 month = atoi(date.substr(3, 2).c_str());
980 year = atoi(date.substr(6, 4).c_str());
984 year = atoi(date.substr(0, 4).c_str());
985 month = atoi(date.substr(5, 2).c_str());
986 day = atoi(date.substr(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.substr(0, 2).c_str());
998 minute = atoi(time.substr(3, 2).c_str());
999 second = atoi(time.substr(6, 2).c_str());
1001 SetTime(hour, minute, second);
1004 void CDateTime::SetFromRFC1123DateTime(const CStdString &dateTime)
1006 CStdString date = dateTime;
1007 StringUtils::Trim(date);
1009 if (date.size() != 29)
1012 int day = strtol(date.substr(5, 2).c_str(), NULL, 10);
1014 CStdString strMonth = date.substr(8, 3);
1016 for (unsigned int index = 0; index < 12; index++)
1018 if (strMonth.Equals(MONTH_NAMES[index]))
1028 int year = strtol(date.substr(12, 4).c_str(), NULL, 10);
1029 int hour = strtol(date.substr(17, 2).c_str(), NULL, 10);
1030 int min = strtol(date.substr(20, 2).c_str(), NULL, 10);
1031 int sec = strtol(date.substr(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.empty() ? 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 size_t length = strFormat.size();
1048 for (size_t 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)) != std::string::npos &&
1057 pos<strFormat.size()) && strFormat[pos+1]=='\'') {}
1060 if (pos != std::string::npos)
1062 // Extract string between ' '
1063 strPart=strFormat.substr(i + 1, pos - i - 1);
1068 strPart=strFormat.substr(i + 1, length - i - 1);
1072 strPart.Replace("''", "'");
1076 else if (c=='h' || c=='H') // parse hour (H="24 hour clock")
1080 int pos=strFormat.find_first_not_of(c,i+1);
1083 // Get length of the hour mask, eg. HH
1089 // mask ends at the end of the string, extract it
1090 partLength=length-i;
1094 int hour=dateTime.wHour;
1096 { // recalc to 12 hour clock
1098 hour -= (12 * (hour > 12));
1100 hour += (12 * (hour < 1));
1103 // Format hour string with the length of the mask
1106 str = StringUtils::Format("%d", hour);
1108 str = StringUtils::Format("%02d", hour);
1112 else if (c=='m') // parse minutes
1116 int pos=strFormat.find_first_not_of(c,i+1);
1119 // Get length of the minute mask, eg. mm
1125 // mask ends at the end of the string, extract it
1126 partLength=length-i;
1130 // Format minute string with the length of the mask
1133 str = StringUtils::Format("%d", dateTime.wMinute);
1135 str = StringUtils::Format("%02d", dateTime.wMinute);
1139 else if (c=='s') // parse seconds
1143 int pos=strFormat.find_first_not_of(c,i+1);
1146 // Get length of the seconds mask, eg. ss
1152 // mask ends at the end of the string, extract it
1153 partLength=length-i;
1159 // Format seconds string with the length of the mask
1162 str = StringUtils::Format("%d", dateTime.wSecond);
1164 str = StringUtils::Format("%02d", dateTime.wSecond);
1169 strOut.erase(strOut.size()-1,1);
1171 else if (c=='x') // add meridiem symbol
1173 int pos=strFormat.find_first_not_of(c,i+1);
1176 // Get length of the meridiem mask
1181 // mask ends at the end of the string, extract it
1185 strOut+=strMeridiem;
1187 else // everything else pass to output
1194 CStdString CDateTime::GetAsLocalizedDate(bool longDate/*=false*/, bool withShortNames/*=true*/) const
1196 return GetAsLocalizedDate(g_langInfo.GetDateFormat(longDate), withShortNames);
1199 CStdString CDateTime::GetAsLocalizedDate(const CStdString &strFormat, bool withShortNames/*=true*/) const
1203 SYSTEMTIME dateTime;
1204 GetAsSystemTime(dateTime);
1206 size_t length = strFormat.size();
1207 for (size_t 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)) != std::string::npos &&
1216 pos < strFormat.size()) &&
1217 strFormat[pos + 1] == '\'') {}
1220 if (pos != std::string::npos)
1222 // Extract string between ' '
1223 strPart = strFormat.substr(i + 1, pos - i - 1);
1228 strPart = strFormat.substr(i + 1, length - i - 1);
1231 strPart.Replace("''", "'");
1234 else if (c=='D' || c=='d') // parse days
1236 size_t partLength=0;
1238 size_t pos = strFormat.find_first_not_of(c, i+1);
1239 if (pos != std::string::npos)
1241 // Get length of the day mask, eg. DDDD
1247 // mask ends at the end of the string, extract it
1248 partLength=length-i;
1252 // Format string with the length of the mask
1254 if (partLength==1) // single-digit number
1255 str = StringUtils::Format("%d", dateTime.wDay);
1256 else if (partLength==2) // two-digit number
1257 str = StringUtils::Format("%02d", dateTime.wDay);
1258 else // Day of week string
1260 int wday = dateTime.wDayOfWeek;
1261 if (wday < 1 || wday > 7) wday = 7;
1262 str = g_localizeStrings.Get(((withShortNames || c =='d') ? 40 : 10) + wday);
1266 else if (c=='M' || c=='m') // parse month
1268 size_t partLength=0;
1270 size_t pos=strFormat.find_first_not_of(c,i+1);
1271 if (pos != std::string::npos)
1273 // Get length of the month mask, eg. MMMM
1279 // mask ends at the end of the string, extract it
1280 partLength=length-i;
1284 // Format string with the length of the mask
1286 if (partLength==1) // single-digit number
1287 str = StringUtils::Format("%d", dateTime.wMonth);
1288 else if (partLength==2) // two-digit number
1289 str = StringUtils::Format("%02d", dateTime.wMonth);
1290 else // Month string
1292 int wmonth = dateTime.wMonth;
1293 if (wmonth < 1 || wmonth > 12) wmonth = 12;
1294 str = g_localizeStrings.Get(((withShortNames || c =='m') ? 50 : 20) + wmonth);
1298 else if (c=='Y' || c =='y') // parse year
1300 size_t partLength = 0;
1302 size_t pos = strFormat.find_first_not_of(c,i+1);
1303 if (pos != std::string::npos)
1305 // Get length of the year mask, eg. YYYY
1311 // mask ends at the end of the string, extract it
1312 partLength=length-i;
1316 // Format string with the length of the mask
1317 CStdString str = StringUtils::Format("%d", dateTime.wYear); // four-digit number
1318 if (partLength <= 2)
1319 str.erase(0, 2); // two-digit number
1323 else // everything else pass to output
1330 CStdString CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withSeconds/*=true*/) const
1332 return GetAsLocalizedDate(longDate)+" "+GetAsLocalizedTime("", withSeconds);
1335 CDateTime CDateTime::GetAsUTCDateTime() const
1337 CDateTime time(m_time);
1338 time += GetTimezoneBias();
1342 CStdString CDateTime::GetAsRFC1123DateTime() const
1344 CDateTime time(GetAsUTCDateTime());
1346 int weekDay = time.GetDayOfWeek();
1349 else if (weekDay > 6)
1351 if (weekDay != time.GetDayOfWeek())
1352 CLog::Log(LOGWARNING, "Invalid day of week %d in %s", time.GetDayOfWeek(), time.GetAsDBDateTime().c_str());
1354 int month = time.GetMonth();
1357 else if (month > 12)
1359 if (month != time.GetMonth())
1360 CLog::Log(LOGWARNING, "Invalid month %d in %s", time.GetMonth(), time.GetAsDBDateTime().c_str());
1362 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());
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++);