/xbmc/XBDateTime.cpp

http://github.com/xbmc/xbmc · C++ · 1576 lines · 1232 code · 290 blank · 54 comment · 161 complexity · 1cc653f0ef2bad7ba17f98b1f502cb3a MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. #include "XBDateTime.h"
  9. #include "LangInfo.h"
  10. #include "guilib/LocalizeStrings.h"
  11. #include "utils/Archive.h"
  12. #include "utils/StringUtils.h"
  13. #include "utils/XTimeUtils.h"
  14. #include "utils/log.h"
  15. #include <cstdlib>
  16. #define SECONDS_PER_DAY 86400UL
  17. #define SECONDS_PER_HOUR 3600UL
  18. #define SECONDS_PER_MINUTE 60UL
  19. #define SECONDS_TO_FILETIME 10000000UL
  20. static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  21. static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  22. /////////////////////////////////////////////////
  23. //
  24. // CDateTimeSpan
  25. //
  26. CDateTimeSpan::CDateTimeSpan()
  27. {
  28. m_timeSpan.highDateTime = 0;
  29. m_timeSpan.lowDateTime = 0;
  30. }
  31. CDateTimeSpan::CDateTimeSpan(const CDateTimeSpan& span)
  32. {
  33. m_timeSpan.highDateTime = span.m_timeSpan.highDateTime;
  34. m_timeSpan.lowDateTime = span.m_timeSpan.lowDateTime;
  35. }
  36. CDateTimeSpan::CDateTimeSpan(int day, int hour, int minute, int second)
  37. {
  38. SetDateTimeSpan(day, hour, minute, second);
  39. }
  40. bool CDateTimeSpan::operator >(const CDateTimeSpan& right) const
  41. {
  42. return KODI::TIME::CompareFileTime(&m_timeSpan, &right.m_timeSpan) > 0;
  43. }
  44. bool CDateTimeSpan::operator >=(const CDateTimeSpan& right) const
  45. {
  46. return operator >(right) || operator ==(right);
  47. }
  48. bool CDateTimeSpan::operator <(const CDateTimeSpan& right) const
  49. {
  50. return KODI::TIME::CompareFileTime(&m_timeSpan, &right.m_timeSpan) < 0;
  51. }
  52. bool CDateTimeSpan::operator <=(const CDateTimeSpan& right) const
  53. {
  54. return operator <(right) || operator ==(right);
  55. }
  56. bool CDateTimeSpan::operator ==(const CDateTimeSpan& right) const
  57. {
  58. return KODI::TIME::CompareFileTime(&m_timeSpan, &right.m_timeSpan) == 0;
  59. }
  60. bool CDateTimeSpan::operator !=(const CDateTimeSpan& right) const
  61. {
  62. return !operator ==(right);
  63. }
  64. CDateTimeSpan CDateTimeSpan::operator +(const CDateTimeSpan& right) const
  65. {
  66. CDateTimeSpan left(*this);
  67. ULARGE_INTEGER timeLeft;
  68. left.ToULargeInt(timeLeft);
  69. ULARGE_INTEGER timeRight;
  70. right.ToULargeInt(timeRight);
  71. timeLeft.QuadPart+=timeRight.QuadPart;
  72. left.FromULargeInt(timeLeft);
  73. return left;
  74. }
  75. CDateTimeSpan CDateTimeSpan::operator -(const CDateTimeSpan& right) const
  76. {
  77. CDateTimeSpan left(*this);
  78. ULARGE_INTEGER timeLeft;
  79. left.ToULargeInt(timeLeft);
  80. ULARGE_INTEGER timeRight;
  81. right.ToULargeInt(timeRight);
  82. timeLeft.QuadPart-=timeRight.QuadPart;
  83. left.FromULargeInt(timeLeft);
  84. return left;
  85. }
  86. const CDateTimeSpan& CDateTimeSpan::operator +=(const CDateTimeSpan& right)
  87. {
  88. ULARGE_INTEGER timeThis;
  89. ToULargeInt(timeThis);
  90. ULARGE_INTEGER timeRight;
  91. right.ToULargeInt(timeRight);
  92. timeThis.QuadPart+=timeRight.QuadPart;
  93. FromULargeInt(timeThis);
  94. return *this;
  95. }
  96. const CDateTimeSpan& CDateTimeSpan::operator -=(const CDateTimeSpan& right)
  97. {
  98. ULARGE_INTEGER timeThis;
  99. ToULargeInt(timeThis);
  100. ULARGE_INTEGER timeRight;
  101. right.ToULargeInt(timeRight);
  102. timeThis.QuadPart-=timeRight.QuadPart;
  103. FromULargeInt(timeThis);
  104. return *this;
  105. }
  106. void CDateTimeSpan::ToULargeInt(ULARGE_INTEGER& time) const
  107. {
  108. time.u.HighPart = m_timeSpan.highDateTime;
  109. time.u.LowPart = m_timeSpan.lowDateTime;
  110. }
  111. void CDateTimeSpan::FromULargeInt(const ULARGE_INTEGER& time)
  112. {
  113. m_timeSpan.highDateTime = time.u.HighPart;
  114. m_timeSpan.lowDateTime = time.u.LowPart;
  115. }
  116. void CDateTimeSpan::SetDateTimeSpan(int day, int hour, int minute, int second)
  117. {
  118. ULARGE_INTEGER time;
  119. ToULargeInt(time);
  120. time.QuadPart= static_cast<long long>(day) *SECONDS_PER_DAY*SECONDS_TO_FILETIME;
  121. time.QuadPart+= static_cast<long long>(hour) *SECONDS_PER_HOUR*SECONDS_TO_FILETIME;
  122. time.QuadPart+= static_cast<long long>(minute) *SECONDS_PER_MINUTE*SECONDS_TO_FILETIME;
  123. time.QuadPart+= static_cast<long long>(second) *SECONDS_TO_FILETIME;
  124. FromULargeInt(time);
  125. }
  126. void CDateTimeSpan::SetFromTimeString(const std::string& time) // hh:mm
  127. {
  128. if (time.size() >= 5 && time[2] == ':')
  129. {
  130. int hour = atoi(time.substr(0, 2).c_str());
  131. int minutes = atoi(time.substr(3, 2).c_str());
  132. SetDateTimeSpan(0,hour,minutes,0);
  133. }
  134. }
  135. int CDateTimeSpan::GetDays() const
  136. {
  137. ULARGE_INTEGER time;
  138. ToULargeInt(time);
  139. return (int)(time.QuadPart/SECONDS_TO_FILETIME)/SECONDS_PER_DAY;
  140. }
  141. int CDateTimeSpan::GetHours() const
  142. {
  143. ULARGE_INTEGER time;
  144. ToULargeInt(time);
  145. return (int)((time.QuadPart/SECONDS_TO_FILETIME)%SECONDS_PER_DAY)/SECONDS_PER_HOUR;
  146. }
  147. int CDateTimeSpan::GetMinutes() const
  148. {
  149. ULARGE_INTEGER time;
  150. ToULargeInt(time);
  151. return (int)((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)/SECONDS_PER_MINUTE;
  152. }
  153. int CDateTimeSpan::GetSeconds() const
  154. {
  155. ULARGE_INTEGER time;
  156. ToULargeInt(time);
  157. return (int)(((time.QuadPart/SECONDS_TO_FILETIME%SECONDS_PER_DAY)%SECONDS_PER_HOUR)%SECONDS_PER_MINUTE)%SECONDS_PER_MINUTE;
  158. }
  159. int CDateTimeSpan::GetSecondsTotal() const
  160. {
  161. ULARGE_INTEGER time;
  162. ToULargeInt(time);
  163. return (int)(time.QuadPart/SECONDS_TO_FILETIME);
  164. }
  165. void CDateTimeSpan::SetFromPeriod(const std::string &period)
  166. {
  167. long days = atoi(period.c_str());
  168. // find the first non-space and non-number
  169. size_t pos = period.find_first_not_of("0123456789 ", 0);
  170. if (pos != std::string::npos)
  171. {
  172. std::string units = period.substr(pos, 3);
  173. if (StringUtils::EqualsNoCase(units, "wee"))
  174. days *= 7;
  175. else if (StringUtils::EqualsNoCase(units, "mon"))
  176. days *= 31;
  177. }
  178. SetDateTimeSpan(days, 0, 0, 0);
  179. }
  180. /////////////////////////////////////////////////
  181. //
  182. // CDateTime
  183. //
  184. CDateTime::CDateTime()
  185. {
  186. Reset();
  187. }
  188. CDateTime::CDateTime(const KODI::TIME::SystemTime& time)
  189. {
  190. // we store internally as a FileTime
  191. m_state = ToFileTime(time, m_time) ? valid : invalid;
  192. }
  193. CDateTime::CDateTime(const KODI::TIME::FileTime& time)
  194. {
  195. m_time=time;
  196. SetValid(true);
  197. }
  198. CDateTime::CDateTime(const CDateTime& time)
  199. {
  200. m_time=time.m_time;
  201. m_state=time.m_state;
  202. }
  203. CDateTime::CDateTime(const time_t& time)
  204. {
  205. m_state = ToFileTime(time, m_time) ? valid : invalid;
  206. }
  207. CDateTime::CDateTime(const tm& time)
  208. {
  209. m_state = ToFileTime(time, m_time) ? valid : invalid;
  210. }
  211. CDateTime::CDateTime(int year, int month, int day, int hour, int minute, int second)
  212. {
  213. SetDateTime(year, month, day, hour, minute, second);
  214. }
  215. CDateTime CDateTime::GetCurrentDateTime()
  216. {
  217. // get the current time
  218. KODI::TIME::SystemTime time;
  219. KODI::TIME::GetLocalTime(&time);
  220. return CDateTime(time);
  221. }
  222. CDateTime CDateTime::GetUTCDateTime()
  223. {
  224. CDateTime time(GetCurrentDateTime());
  225. time += GetTimezoneBias();
  226. return time;
  227. }
  228. const CDateTime& CDateTime::operator=(const KODI::TIME::SystemTime& right)
  229. {
  230. m_state = ToFileTime(right, m_time) ? valid : invalid;
  231. return *this;
  232. }
  233. const CDateTime& CDateTime::operator=(const KODI::TIME::FileTime& right)
  234. {
  235. m_time=right;
  236. SetValid(true);
  237. return *this;
  238. }
  239. const CDateTime& CDateTime::operator =(const time_t& right)
  240. {
  241. m_state = ToFileTime(right, m_time) ? valid : invalid;
  242. return *this;
  243. }
  244. const CDateTime& CDateTime::operator =(const tm& right)
  245. {
  246. m_state = ToFileTime(right, m_time) ? valid : invalid;
  247. return *this;
  248. }
  249. bool CDateTime::operator >(const CDateTime& right) const
  250. {
  251. return operator >(right.m_time);
  252. }
  253. bool CDateTime::operator >=(const CDateTime& right) const
  254. {
  255. return operator >(right) || operator ==(right);
  256. }
  257. bool CDateTime::operator <(const CDateTime& right) const
  258. {
  259. return operator <(right.m_time);
  260. }
  261. bool CDateTime::operator <=(const CDateTime& right) const
  262. {
  263. return operator <(right) || operator ==(right);
  264. }
  265. bool CDateTime::operator ==(const CDateTime& right) const
  266. {
  267. return operator ==(right.m_time);
  268. }
  269. bool CDateTime::operator !=(const CDateTime& right) const
  270. {
  271. return !operator ==(right);
  272. }
  273. bool CDateTime::operator>(const KODI::TIME::FileTime& right) const
  274. {
  275. return KODI::TIME::CompareFileTime(&m_time, &right) > 0;
  276. }
  277. bool CDateTime::operator>=(const KODI::TIME::FileTime& right) const
  278. {
  279. return operator >(right) || operator ==(right);
  280. }
  281. bool CDateTime::operator<(const KODI::TIME::FileTime& right) const
  282. {
  283. return KODI::TIME::CompareFileTime(&m_time, &right) < 0;
  284. }
  285. bool CDateTime::operator<=(const KODI::TIME::FileTime& right) const
  286. {
  287. return operator <(right) || operator ==(right);
  288. }
  289. bool CDateTime::operator==(const KODI::TIME::FileTime& right) const
  290. {
  291. return KODI::TIME::CompareFileTime(&m_time, &right) == 0;
  292. }
  293. bool CDateTime::operator!=(const KODI::TIME::FileTime& right) const
  294. {
  295. return !operator ==(right);
  296. }
  297. bool CDateTime::operator>(const KODI::TIME::SystemTime& right) const
  298. {
  299. KODI::TIME::FileTime time;
  300. ToFileTime(right, time);
  301. return operator >(time);
  302. }
  303. bool CDateTime::operator>=(const KODI::TIME::SystemTime& right) const
  304. {
  305. return operator >(right) || operator ==(right);
  306. }
  307. bool CDateTime::operator<(const KODI::TIME::SystemTime& right) const
  308. {
  309. KODI::TIME::FileTime time;
  310. ToFileTime(right, time);
  311. return operator <(time);
  312. }
  313. bool CDateTime::operator<=(const KODI::TIME::SystemTime& right) const
  314. {
  315. return operator <(right) || operator ==(right);
  316. }
  317. bool CDateTime::operator==(const KODI::TIME::SystemTime& right) const
  318. {
  319. KODI::TIME::FileTime time;
  320. ToFileTime(right, time);
  321. return operator ==(time);
  322. }
  323. bool CDateTime::operator!=(const KODI::TIME::SystemTime& right) const
  324. {
  325. return !operator ==(right);
  326. }
  327. bool CDateTime::operator >(const time_t& right) const
  328. {
  329. KODI::TIME::FileTime time;
  330. ToFileTime(right, time);
  331. return operator >(time);
  332. }
  333. bool CDateTime::operator >=(const time_t& right) const
  334. {
  335. return operator >(right) || operator ==(right);
  336. }
  337. bool CDateTime::operator <(const time_t& right) const
  338. {
  339. KODI::TIME::FileTime time;
  340. ToFileTime(right, time);
  341. return operator <(time);
  342. }
  343. bool CDateTime::operator <=(const time_t& right) const
  344. {
  345. return operator <(right) || operator ==(right);
  346. }
  347. bool CDateTime::operator ==(const time_t& right) const
  348. {
  349. KODI::TIME::FileTime time;
  350. ToFileTime(right, time);
  351. return operator ==(time);
  352. }
  353. bool CDateTime::operator !=(const time_t& right) const
  354. {
  355. return !operator ==(right);
  356. }
  357. bool CDateTime::operator >(const tm& right) const
  358. {
  359. KODI::TIME::FileTime time;
  360. ToFileTime(right, time);
  361. return operator >(time);
  362. }
  363. bool CDateTime::operator >=(const tm& right) const
  364. {
  365. return operator >(right) || operator ==(right);
  366. }
  367. bool CDateTime::operator <(const tm& right) const
  368. {
  369. KODI::TIME::FileTime time;
  370. ToFileTime(right, time);
  371. return operator <(time);
  372. }
  373. bool CDateTime::operator <=(const tm& right) const
  374. {
  375. return operator <(right) || operator ==(right);
  376. }
  377. bool CDateTime::operator ==(const tm& right) const
  378. {
  379. KODI::TIME::FileTime time;
  380. ToFileTime(right, time);
  381. return operator ==(time);
  382. }
  383. bool CDateTime::operator !=(const tm& right) const
  384. {
  385. return !operator ==(right);
  386. }
  387. CDateTime CDateTime::operator +(const CDateTimeSpan& right) const
  388. {
  389. CDateTime left(*this);
  390. ULARGE_INTEGER timeLeft;
  391. left.ToULargeInt(timeLeft);
  392. ULARGE_INTEGER timeRight;
  393. right.ToULargeInt(timeRight);
  394. timeLeft.QuadPart+=timeRight.QuadPart;
  395. left.FromULargeInt(timeLeft);
  396. return left;
  397. }
  398. CDateTime CDateTime::operator -(const CDateTimeSpan& right) const
  399. {
  400. CDateTime left(*this);
  401. ULARGE_INTEGER timeLeft;
  402. left.ToULargeInt(timeLeft);
  403. ULARGE_INTEGER timeRight;
  404. right.ToULargeInt(timeRight);
  405. timeLeft.QuadPart-=timeRight.QuadPart;
  406. left.FromULargeInt(timeLeft);
  407. return left;
  408. }
  409. const CDateTime& CDateTime::operator +=(const CDateTimeSpan& right)
  410. {
  411. ULARGE_INTEGER timeThis;
  412. ToULargeInt(timeThis);
  413. ULARGE_INTEGER timeRight;
  414. right.ToULargeInt(timeRight);
  415. timeThis.QuadPart+=timeRight.QuadPart;
  416. FromULargeInt(timeThis);
  417. return *this;
  418. }
  419. const CDateTime& CDateTime::operator -=(const CDateTimeSpan& right)
  420. {
  421. ULARGE_INTEGER timeThis;
  422. ToULargeInt(timeThis);
  423. ULARGE_INTEGER timeRight;
  424. right.ToULargeInt(timeRight);
  425. timeThis.QuadPart-=timeRight.QuadPart;
  426. FromULargeInt(timeThis);
  427. return *this;
  428. }
  429. CDateTimeSpan CDateTime::operator -(const CDateTime& right) const
  430. {
  431. CDateTimeSpan left;
  432. ULARGE_INTEGER timeLeft;
  433. left.ToULargeInt(timeLeft);
  434. ULARGE_INTEGER timeThis;
  435. ToULargeInt(timeThis);
  436. ULARGE_INTEGER timeRight;
  437. right.ToULargeInt(timeRight);
  438. timeLeft.QuadPart=timeThis.QuadPart-timeRight.QuadPart;
  439. left.FromULargeInt(timeLeft);
  440. return left;
  441. }
  442. CDateTime::operator KODI::TIME::FileTime() const
  443. {
  444. return m_time;
  445. }
  446. void CDateTime::Archive(CArchive& ar)
  447. {
  448. if (ar.IsStoring())
  449. {
  450. ar<<(int)m_state;
  451. if (m_state==valid)
  452. {
  453. KODI::TIME::SystemTime st;
  454. GetAsSystemTime(st);
  455. ar<<st;
  456. }
  457. }
  458. else
  459. {
  460. Reset();
  461. int state;
  462. ar >> state;
  463. m_state = CDateTime::STATE(state);
  464. if (m_state==valid)
  465. {
  466. KODI::TIME::SystemTime st;
  467. ar>>st;
  468. ToFileTime(st, m_time);
  469. }
  470. }
  471. }
  472. void CDateTime::Reset()
  473. {
  474. SetDateTime(1601, 1, 1, 0, 0, 0);
  475. SetValid(false);
  476. }
  477. void CDateTime::SetValid(bool yesNo)
  478. {
  479. m_state=yesNo ? valid : invalid;
  480. }
  481. bool CDateTime::IsValid() const
  482. {
  483. return m_state==valid;
  484. }
  485. bool CDateTime::ToFileTime(const KODI::TIME::SystemTime& time, KODI::TIME::FileTime& fileTime) const
  486. {
  487. return KODI::TIME::SystemTimeToFileTime(&time, &fileTime) == 1 &&
  488. (fileTime.lowDateTime > 0 || fileTime.highDateTime > 0);
  489. }
  490. bool CDateTime::ToFileTime(const time_t& time, KODI::TIME::FileTime& fileTime) const
  491. {
  492. long long ll = time;
  493. ll *= 10000000ll;
  494. ll += 0x19DB1DED53E8000LL;
  495. fileTime.lowDateTime = (DWORD)(ll & 0xFFFFFFFF);
  496. fileTime.highDateTime = (DWORD)(ll >> 32);
  497. return true;
  498. }
  499. bool CDateTime::ToFileTime(const tm& time, KODI::TIME::FileTime& fileTime) const
  500. {
  501. KODI::TIME::SystemTime st = {0};
  502. st.year = time.tm_year + 1900;
  503. st.month = time.tm_mon + 1;
  504. st.dayOfWeek = time.tm_wday;
  505. st.day = time.tm_mday;
  506. st.hour = time.tm_hour;
  507. st.minute = time.tm_min;
  508. st.second = time.tm_sec;
  509. return SystemTimeToFileTime(&st, &fileTime) == 1;
  510. }
  511. void CDateTime::ToULargeInt(ULARGE_INTEGER& time) const
  512. {
  513. time.u.HighPart = m_time.highDateTime;
  514. time.u.LowPart = m_time.lowDateTime;
  515. }
  516. void CDateTime::FromULargeInt(const ULARGE_INTEGER& time)
  517. {
  518. m_time.highDateTime = time.u.HighPart;
  519. m_time.lowDateTime = time.u.LowPart;
  520. }
  521. bool CDateTime::SetFromDateString(const std::string &date)
  522. {
  523. //! @todo STRING_CLEANUP
  524. if (date.empty())
  525. {
  526. SetValid(false);
  527. return false;
  528. }
  529. if (SetFromDBDate(date))
  530. return true;
  531. const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december",NULL};
  532. int j=0;
  533. size_t iDayPos = date.find("day");
  534. size_t iPos = date.find(' ');
  535. if (iDayPos < iPos && iDayPos != std::string::npos)
  536. {
  537. iDayPos = iPos + 1;
  538. iPos = date.find(' ', iPos+1);
  539. }
  540. else
  541. iDayPos = 0;
  542. std::string strMonth = date.substr(iDayPos, iPos - iDayPos);
  543. if (strMonth.empty())
  544. return false;
  545. size_t iPos2 = date.find(",");
  546. std::string strDay = (date.size() >= iPos) ? date.substr(iPos, iPos2-iPos) : "";
  547. std::string strYear = date.substr(date.find(' ', iPos2) + 1);
  548. while (months[j] && StringUtils::CompareNoCase(strMonth, months[j]) != 0)
  549. j++;
  550. if (!months[j])
  551. return false;
  552. return SetDateTime(atol(strYear.c_str()),j+1,atol(strDay.c_str()),0,0,0);
  553. }
  554. int CDateTime::GetDay() const
  555. {
  556. KODI::TIME::SystemTime st;
  557. GetAsSystemTime(st);
  558. return st.day;
  559. }
  560. int CDateTime::GetMonth() const
  561. {
  562. KODI::TIME::SystemTime st;
  563. GetAsSystemTime(st);
  564. return st.month;
  565. }
  566. int CDateTime::GetYear() const
  567. {
  568. KODI::TIME::SystemTime st;
  569. GetAsSystemTime(st);
  570. return st.year;
  571. }
  572. int CDateTime::GetHour() const
  573. {
  574. KODI::TIME::SystemTime st;
  575. GetAsSystemTime(st);
  576. return st.hour;
  577. }
  578. int CDateTime::GetMinute() const
  579. {
  580. KODI::TIME::SystemTime st;
  581. GetAsSystemTime(st);
  582. return st.minute;
  583. }
  584. int CDateTime::GetSecond() const
  585. {
  586. KODI::TIME::SystemTime st;
  587. GetAsSystemTime(st);
  588. return st.second;
  589. }
  590. int CDateTime::GetDayOfWeek() const
  591. {
  592. KODI::TIME::SystemTime st;
  593. GetAsSystemTime(st);
  594. return st.dayOfWeek;
  595. }
  596. int CDateTime::GetMinuteOfDay() const
  597. {
  598. KODI::TIME::SystemTime st;
  599. GetAsSystemTime(st);
  600. return st.hour * 60 + st.minute;
  601. }
  602. bool CDateTime::SetDateTime(int year, int month, int day, int hour, int minute, int second)
  603. {
  604. KODI::TIME::SystemTime st = {0};
  605. st.year = year;
  606. st.month = month;
  607. st.day = day;
  608. st.hour = hour;
  609. st.minute = minute;
  610. st.second = second;
  611. m_state = ToFileTime(st, m_time) ? valid : invalid;
  612. return m_state == valid;
  613. }
  614. bool CDateTime::SetDate(int year, int month, int day)
  615. {
  616. return SetDateTime(year, month, day, 0, 0, 0);
  617. }
  618. bool CDateTime::SetTime(int hour, int minute, int second)
  619. {
  620. // 01.01.1601 00:00:00 is 0 as filetime
  621. return SetDateTime(1601, 1, 1, hour, minute, second);
  622. }
  623. void CDateTime::GetAsSystemTime(KODI::TIME::SystemTime& time) const
  624. {
  625. FileTimeToSystemTime(&m_time, &time);
  626. }
  627. #define UNIX_BASE_TIME 116444736000000000LL /* nanoseconds since epoch */
  628. void CDateTime::GetAsTime(time_t& time) const
  629. {
  630. long long ll = (static_cast<long long>(m_time.highDateTime) << 32) + m_time.lowDateTime;
  631. time=(time_t)((ll - UNIX_BASE_TIME) / 10000000);
  632. }
  633. void CDateTime::GetAsTm(tm& time) const
  634. {
  635. KODI::TIME::SystemTime st;
  636. GetAsSystemTime(st);
  637. time.tm_year = st.year - 1900;
  638. time.tm_mon = st.month - 1;
  639. time.tm_wday = st.dayOfWeek;
  640. time.tm_mday = st.day;
  641. time.tm_hour = st.hour;
  642. time.tm_min = st.minute;
  643. time.tm_sec = st.second;
  644. mktime(&time);
  645. }
  646. void CDateTime::GetAsTimeStamp(KODI::TIME::FileTime& time) const
  647. {
  648. KODI::TIME::LocalFileTimeToFileTime(&m_time, &time);
  649. }
  650. std::string CDateTime::GetAsDBDate() const
  651. {
  652. KODI::TIME::SystemTime st;
  653. GetAsSystemTime(st);
  654. return StringUtils::Format("%04i-%02i-%02i", st.year, st.month, st.day);
  655. }
  656. std::string CDateTime::GetAsDBTime() const
  657. {
  658. KODI::TIME::SystemTime st;
  659. GetAsSystemTime(st);
  660. return StringUtils::Format("%02i:%02i:%02i", st.hour, st.minute, st.second);
  661. }
  662. std::string CDateTime::GetAsDBDateTime() const
  663. {
  664. KODI::TIME::SystemTime st;
  665. GetAsSystemTime(st);
  666. return StringUtils::Format("%04i-%02i-%02i %02i:%02i:%02i", st.year, st.month, st.day, st.hour,
  667. st.minute, st.second);
  668. }
  669. std::string CDateTime::GetAsSaveString() const
  670. {
  671. KODI::TIME::SystemTime st;
  672. GetAsSystemTime(st);
  673. return StringUtils::Format("%04i%02i%02i_%02i%02i%02i", st.year, st.month, st.day, st.hour,
  674. st.minute, st.second);
  675. }
  676. bool CDateTime::SetFromUTCDateTime(const CDateTime &dateTime)
  677. {
  678. CDateTime tmp(dateTime);
  679. tmp -= GetTimezoneBias();
  680. m_time = tmp.m_time;
  681. m_state = tmp.m_state;
  682. return m_state == valid;
  683. }
  684. static bool bGotTimezoneBias = false;
  685. void CDateTime::ResetTimezoneBias(void)
  686. {
  687. bGotTimezoneBias = false;
  688. }
  689. CDateTimeSpan CDateTime::GetTimezoneBias(void)
  690. {
  691. static CDateTimeSpan timezoneBias;
  692. if (!bGotTimezoneBias)
  693. {
  694. bGotTimezoneBias = true;
  695. KODI::TIME::TimeZoneInformation tz;
  696. switch (KODI::TIME::GetTimeZoneInformation(&tz))
  697. {
  698. case KODI::TIME::KODI_TIME_ZONE_ID_DAYLIGHT:
  699. timezoneBias = CDateTimeSpan(0, 0, tz.bias + tz.daylightBias, 0);
  700. break;
  701. case KODI::TIME::KODI_TIME_ZONE_ID_STANDARD:
  702. timezoneBias = CDateTimeSpan(0, 0, tz.bias + tz.standardBias, 0);
  703. break;
  704. case KODI::TIME::KODI_TIME_ZONE_ID_UNKNOWN:
  705. timezoneBias = CDateTimeSpan(0, 0, tz.bias, 0);
  706. break;
  707. }
  708. }
  709. return timezoneBias;
  710. }
  711. bool CDateTime::SetFromUTCDateTime(const time_t &dateTime)
  712. {
  713. CDateTime tmp(dateTime);
  714. return SetFromUTCDateTime(tmp);
  715. }
  716. bool CDateTime::SetFromW3CDate(const std::string &dateTime)
  717. {
  718. std::string date;
  719. size_t posT = dateTime.find("T");
  720. if(posT != std::string::npos)
  721. date = dateTime.substr(0, posT);
  722. else
  723. date = dateTime;
  724. int year = 0, month = 1, day = 1;
  725. if (date.size() >= 4)
  726. year = atoi(date.substr(0, 4).c_str());
  727. if (date.size() >= 10)
  728. {
  729. month = atoi(date.substr(5, 2).c_str());
  730. day = atoi(date.substr(8, 2).c_str());
  731. }
  732. CDateTime tmpDateTime(year, month, day, 0, 0, 0);
  733. if (tmpDateTime.IsValid())
  734. *this = tmpDateTime;
  735. return IsValid();
  736. }
  737. bool CDateTime::SetFromW3CDateTime(const std::string &dateTime, bool ignoreTimezone /* = false */)
  738. {
  739. std::string date, time, zone;
  740. size_t posT = dateTime.find("T");
  741. if(posT != std::string::npos)
  742. {
  743. date = dateTime.substr(0, posT);
  744. std::string::size_type posZ = dateTime.find_first_of("+-Z", posT);
  745. if(posZ == std::string::npos)
  746. time = dateTime.substr(posT + 1);
  747. else
  748. {
  749. time = dateTime.substr(posT + 1, posZ - posT - 1);
  750. zone = dateTime.substr(posZ);
  751. }
  752. }
  753. else
  754. date = dateTime;
  755. int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
  756. if (date.size() >= 4)
  757. year = atoi(date.substr(0, 4).c_str());
  758. if (date.size() >= 10)
  759. {
  760. month = atoi(date.substr(5, 2).c_str());
  761. day = atoi(date.substr(8, 2).c_str());
  762. }
  763. if (time.length() >= 5)
  764. {
  765. hour = atoi(time.substr(0, 2).c_str());
  766. min = atoi(time.substr(3, 2).c_str());
  767. }
  768. if (time.length() >= 8)
  769. sec = atoi(time.substr(6, 2).c_str());
  770. CDateTime tmpDateTime(year, month, day, hour, min, sec);
  771. if (!tmpDateTime.IsValid())
  772. return false;
  773. if (!ignoreTimezone && !zone.empty())
  774. {
  775. // check if the timezone is UTC
  776. if (StringUtils::StartsWith(zone, "Z"))
  777. return SetFromUTCDateTime(tmpDateTime);
  778. else
  779. {
  780. // retrieve the timezone offset (ignoring the + or -)
  781. CDateTimeSpan zoneSpan; zoneSpan.SetFromTimeString(zone.substr(1));
  782. if (zoneSpan.GetSecondsTotal() != 0)
  783. {
  784. if (StringUtils::StartsWith(zone, "+"))
  785. tmpDateTime -= zoneSpan;
  786. else if (StringUtils::StartsWith(zone, "-"))
  787. tmpDateTime += zoneSpan;
  788. }
  789. }
  790. }
  791. *this = tmpDateTime;
  792. return IsValid();
  793. }
  794. bool CDateTime::SetFromDBDateTime(const std::string &dateTime)
  795. {
  796. // assumes format YYYY-MM-DD HH:MM:SS
  797. if (dateTime.size() == 19)
  798. {
  799. int year = atoi(dateTime.substr(0, 4).c_str());
  800. int month = atoi(dateTime.substr(5, 2).c_str());
  801. int day = atoi(dateTime.substr(8, 2).c_str());
  802. int hour = atoi(dateTime.substr(11, 2).c_str());
  803. int min = atoi(dateTime.substr(14, 2).c_str());
  804. int sec = atoi(dateTime.substr(17, 2).c_str());
  805. return SetDateTime(year, month, day, hour, min, sec);
  806. }
  807. return false;
  808. }
  809. bool CDateTime::SetFromDBDate(const std::string &date)
  810. {
  811. if (date.size() < 10)
  812. return false;
  813. // assumes format:
  814. // YYYY-MM-DD or DD-MM-YYYY
  815. const static std::string sep_chars = "-./";
  816. int year = 0, month = 0, day = 0;
  817. if (sep_chars.find(date[2]) != std::string::npos)
  818. {
  819. day = atoi(date.substr(0, 2).c_str());
  820. month = atoi(date.substr(3, 2).c_str());
  821. year = atoi(date.substr(6, 4).c_str());
  822. }
  823. else if (sep_chars.find(date[4]) != std::string::npos)
  824. {
  825. year = atoi(date.substr(0, 4).c_str());
  826. month = atoi(date.substr(5, 2).c_str());
  827. day = atoi(date.substr(8, 2).c_str());
  828. }
  829. return SetDate(year, month, day);
  830. }
  831. bool CDateTime::SetFromDBTime(const std::string &time)
  832. {
  833. if (time.size() < 5)
  834. return false;
  835. int hour;
  836. int minute;
  837. int second = 0;
  838. // HH:MM or HH:MM:SS
  839. hour = atoi(time.substr(0, 2).c_str());
  840. minute = atoi(time.substr(3, 2).c_str());
  841. // HH:MM:SS
  842. if (time.size() == 8)
  843. second = atoi(time.substr(6, 2).c_str());
  844. return SetTime(hour, minute, second);
  845. }
  846. bool CDateTime::SetFromRFC1123DateTime(const std::string &dateTime)
  847. {
  848. std::string date = dateTime;
  849. StringUtils::Trim(date);
  850. if (date.size() != 29)
  851. return false;
  852. int day = strtol(date.substr(5, 2).c_str(), NULL, 10);
  853. std::string strMonth = date.substr(8, 3);
  854. int month = 0;
  855. for (unsigned int index = 0; index < 12; index++)
  856. {
  857. if (strMonth == MONTH_NAMES[index])
  858. {
  859. month = index + 1;
  860. break;
  861. }
  862. }
  863. if (month < 1)
  864. return false;
  865. int year = strtol(date.substr(12, 4).c_str(), NULL, 10);
  866. int hour = strtol(date.substr(17, 2).c_str(), NULL, 10);
  867. int min = strtol(date.substr(20, 2).c_str(), NULL, 10);
  868. int sec = strtol(date.substr(23, 2).c_str(), NULL, 10);
  869. return SetDateTime(year, month, day, hour, min, sec);
  870. }
  871. CDateTime CDateTime::FromDateString(const std::string &date)
  872. {
  873. CDateTime dt;
  874. dt.SetFromDateString(date);
  875. return dt;
  876. }
  877. CDateTime CDateTime::FromDBDateTime(const std::string &dateTime)
  878. {
  879. CDateTime dt;
  880. dt.SetFromDBDateTime(dateTime);
  881. return dt;
  882. }
  883. CDateTime CDateTime::FromDBDate(const std::string &date)
  884. {
  885. CDateTime dt;
  886. dt.SetFromDBDate(date);
  887. return dt;
  888. }
  889. CDateTime CDateTime::FromDBTime(const std::string &time)
  890. {
  891. CDateTime dt;
  892. dt.SetFromDBTime(time);
  893. return dt;
  894. }
  895. CDateTime CDateTime::FromW3CDate(const std::string &date)
  896. {
  897. CDateTime dt;
  898. dt.SetFromW3CDate(date);
  899. return dt;
  900. }
  901. CDateTime CDateTime::FromW3CDateTime(const std::string &date, bool ignoreTimezone /* = false */)
  902. {
  903. CDateTime dt;
  904. dt.SetFromW3CDateTime(date, ignoreTimezone);
  905. return dt;
  906. }
  907. CDateTime CDateTime::FromUTCDateTime(const CDateTime &dateTime)
  908. {
  909. CDateTime dt;
  910. dt.SetFromUTCDateTime(dateTime);
  911. return dt;
  912. }
  913. CDateTime CDateTime::FromUTCDateTime(const time_t &dateTime)
  914. {
  915. CDateTime dt;
  916. dt.SetFromUTCDateTime(dateTime);
  917. return dt;
  918. }
  919. CDateTime CDateTime::FromRFC1123DateTime(const std::string &dateTime)
  920. {
  921. CDateTime dt;
  922. dt.SetFromRFC1123DateTime(dateTime);
  923. return dt;
  924. }
  925. std::string CDateTime::GetAsLocalizedTime(const std::string &format, bool withSeconds) const
  926. {
  927. std::string strOut;
  928. const std::string& strFormat = format.empty() ? g_langInfo.GetTimeFormat() : format;
  929. KODI::TIME::SystemTime dateTime;
  930. GetAsSystemTime(dateTime);
  931. // Prefetch meridiem symbol
  932. const std::string& strMeridiem =
  933. CLangInfo::MeridiemSymbolToString(dateTime.hour > 11 ? MeridiemSymbolPM : MeridiemSymbolAM);
  934. size_t length = strFormat.size();
  935. for (size_t i=0; i < length; ++i)
  936. {
  937. char c=strFormat[i];
  938. if (c=='\'')
  939. {
  940. // To be able to display a "'" in the string,
  941. // find the last "'" that doesn't follow a "'"
  942. size_t pos=i + 1;
  943. while(((pos = strFormat.find(c, pos + 1)) != std::string::npos &&
  944. pos<strFormat.size()) && strFormat[pos+1]=='\'') {}
  945. std::string strPart;
  946. if (pos != std::string::npos)
  947. {
  948. // Extract string between ' '
  949. strPart=strFormat.substr(i + 1, pos - i - 1);
  950. i=pos;
  951. }
  952. else
  953. {
  954. strPart=strFormat.substr(i + 1, length - i - 1);
  955. i=length;
  956. }
  957. StringUtils::Replace(strPart, "''", "'");
  958. strOut+=strPart;
  959. }
  960. else if (c=='h' || c=='H') // parse hour (H="24 hour clock")
  961. {
  962. int partLength=0;
  963. int pos=strFormat.find_first_not_of(c,i+1);
  964. if (pos>-1)
  965. {
  966. // Get length of the hour mask, eg. HH
  967. partLength=pos-i;
  968. i=pos-1;
  969. }
  970. else
  971. {
  972. // mask ends at the end of the string, extract it
  973. partLength=length-i;
  974. i=length;
  975. }
  976. int hour = dateTime.hour;
  977. if (c=='h')
  978. { // recalc to 12 hour clock
  979. if (hour > 11)
  980. hour -= (12 * (hour > 12));
  981. else
  982. hour += (12 * (hour < 1));
  983. }
  984. // Format hour string with the length of the mask
  985. std::string str;
  986. if (partLength==1)
  987. str = StringUtils::Format("%d", hour);
  988. else
  989. str = StringUtils::Format("%02d", hour);
  990. strOut+=str;
  991. }
  992. else if (c=='m') // parse minutes
  993. {
  994. int partLength=0;
  995. int pos=strFormat.find_first_not_of(c,i+1);
  996. if (pos>-1)
  997. {
  998. // Get length of the minute mask, eg. mm
  999. partLength=pos-i;
  1000. i=pos-1;
  1001. }
  1002. else
  1003. {
  1004. // mask ends at the end of the string, extract it
  1005. partLength=length-i;
  1006. i=length;
  1007. }
  1008. // Format minute string with the length of the mask
  1009. std::string str;
  1010. if (partLength==1)
  1011. str = StringUtils::Format("%d", dateTime.minute);
  1012. else
  1013. str = StringUtils::Format("%02d", dateTime.minute);
  1014. strOut+=str;
  1015. }
  1016. else if (c=='s') // parse seconds
  1017. {
  1018. int partLength=0;
  1019. int pos=strFormat.find_first_not_of(c,i+1);
  1020. if (pos>-1)
  1021. {
  1022. // Get length of the seconds mask, eg. ss
  1023. partLength=pos-i;
  1024. i=pos-1;
  1025. }
  1026. else
  1027. {
  1028. // mask ends at the end of the string, extract it
  1029. partLength=length-i;
  1030. i=length;
  1031. }
  1032. if (withSeconds)
  1033. {
  1034. // Format seconds string with the length of the mask
  1035. std::string str;
  1036. if (partLength==1)
  1037. str = StringUtils::Format("%d", dateTime.second);
  1038. else
  1039. str = StringUtils::Format("%02d", dateTime.second);
  1040. strOut+=str;
  1041. }
  1042. else
  1043. strOut.erase(strOut.size()-1,1);
  1044. }
  1045. else if (c=='x') // add meridiem symbol
  1046. {
  1047. int pos=strFormat.find_first_not_of(c,i+1);
  1048. if (pos>-1)
  1049. {
  1050. // Get length of the meridiem mask
  1051. i=pos-1;
  1052. }
  1053. else
  1054. {
  1055. // mask ends at the end of the string, extract it
  1056. i=length;
  1057. }
  1058. strOut+=strMeridiem;
  1059. }
  1060. else // everything else pass to output
  1061. strOut+=c;
  1062. }
  1063. return strOut;
  1064. }
  1065. std::string CDateTime::GetAsLocalizedDate(bool longDate/*=false*/) const
  1066. {
  1067. return GetAsLocalizedDate(g_langInfo.GetDateFormat(longDate));
  1068. }
  1069. std::string CDateTime::GetAsLocalizedDate(const std::string &strFormat) const
  1070. {
  1071. std::string strOut;
  1072. KODI::TIME::SystemTime dateTime;
  1073. GetAsSystemTime(dateTime);
  1074. size_t length = strFormat.size();
  1075. for (size_t i = 0; i < length; ++i)
  1076. {
  1077. char c=strFormat[i];
  1078. if (c=='\'')
  1079. {
  1080. // To be able to display a "'" in the string,
  1081. // find the last "'" that doesn't follow a "'"
  1082. size_t pos = i + 1;
  1083. while(((pos = strFormat.find(c, pos + 1)) != std::string::npos &&
  1084. pos < strFormat.size()) &&
  1085. strFormat[pos + 1] == '\'') {}
  1086. std::string strPart;
  1087. if (pos != std::string::npos)
  1088. {
  1089. // Extract string between ' '
  1090. strPart = strFormat.substr(i + 1, pos - i - 1);
  1091. i = pos;
  1092. }
  1093. else
  1094. {
  1095. strPart = strFormat.substr(i + 1, length - i - 1);
  1096. i = length;
  1097. }
  1098. StringUtils::Replace(strPart, "''", "'");
  1099. strOut+=strPart;
  1100. }
  1101. else if (c=='D' || c=='d') // parse days
  1102. {
  1103. size_t partLength=0;
  1104. size_t pos = strFormat.find_first_not_of(c, i+1);
  1105. if (pos != std::string::npos)
  1106. {
  1107. // Get length of the day mask, eg. DDDD
  1108. partLength=pos-i;
  1109. i=pos-1;
  1110. }
  1111. else
  1112. {
  1113. // mask ends at the end of the string, extract it
  1114. partLength=length-i;
  1115. i=length;
  1116. }
  1117. // Format string with the length of the mask
  1118. std::string str;
  1119. if (partLength==1) // single-digit number
  1120. str = StringUtils::Format("%d", dateTime.day);
  1121. else if (partLength==2) // two-digit number
  1122. str = StringUtils::Format("%02d", dateTime.day);
  1123. else // Day of week string
  1124. {
  1125. int wday = dateTime.dayOfWeek;
  1126. if (wday < 1 || wday > 7) wday = 7;
  1127. str = g_localizeStrings.Get((c =='d' ? 40 : 10) + wday);
  1128. }
  1129. strOut+=str;
  1130. }
  1131. else if (c=='M' || c=='m') // parse month
  1132. {
  1133. size_t partLength=0;
  1134. size_t pos=strFormat.find_first_not_of(c,i+1);
  1135. if (pos != std::string::npos)
  1136. {
  1137. // Get length of the month mask, eg. MMMM
  1138. partLength=pos-i;
  1139. i=pos-1;
  1140. }
  1141. else
  1142. {
  1143. // mask ends at the end of the string, extract it
  1144. partLength=length-i;
  1145. i=length;
  1146. }
  1147. // Format string with the length of the mask
  1148. std::string str;
  1149. if (partLength==1) // single-digit number
  1150. str = StringUtils::Format("%d", dateTime.month);
  1151. else if (partLength==2) // two-digit number
  1152. str = StringUtils::Format("%02d", dateTime.month);
  1153. else // Month string
  1154. {
  1155. int wmonth = dateTime.month;
  1156. if (wmonth < 1 || wmonth > 12) wmonth = 12;
  1157. str = g_localizeStrings.Get((c =='m' ? 50 : 20) + wmonth);
  1158. }
  1159. strOut+=str;
  1160. }
  1161. else if (c=='Y' || c =='y') // parse year
  1162. {
  1163. size_t partLength = 0;
  1164. size_t pos = strFormat.find_first_not_of(c,i+1);
  1165. if (pos != std::string::npos)
  1166. {
  1167. // Get length of the year mask, eg. YYYY
  1168. partLength=pos-i;
  1169. i=pos-1;
  1170. }
  1171. else
  1172. {
  1173. // mask ends at the end of the string, extract it
  1174. partLength=length-i;
  1175. i=length;
  1176. }
  1177. // Format string with the length of the mask
  1178. std::string str = StringUtils::Format("%d", dateTime.year); // four-digit number
  1179. if (partLength <= 2)
  1180. str.erase(0, 2); // two-digit number
  1181. strOut+=str;
  1182. }
  1183. else // everything else pass to output
  1184. strOut+=c;
  1185. }
  1186. return strOut;
  1187. }
  1188. std::string CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withSeconds/*=true*/) const
  1189. {
  1190. return GetAsLocalizedDate(longDate) + ' ' + GetAsLocalizedTime("", withSeconds);
  1191. }
  1192. std::string CDateTime::GetAsLocalizedTime(TIME_FORMAT format, bool withSeconds /* = false */) const
  1193. {
  1194. const std::string timeFormat = g_langInfo.GetTimeFormat();
  1195. bool use12hourclock = timeFormat.find('h') != std::string::npos;
  1196. switch (format)
  1197. {
  1198. case TIME_FORMAT_GUESS:
  1199. return GetAsLocalizedTime("", withSeconds);
  1200. case TIME_FORMAT_SS:
  1201. return GetAsLocalizedTime("ss", true);
  1202. case TIME_FORMAT_MM:
  1203. return GetAsLocalizedTime("mm", true);
  1204. case TIME_FORMAT_MM_SS:
  1205. return GetAsLocalizedTime("mm:ss", true);
  1206. case TIME_FORMAT_HH: // this forces it to a 12 hour clock
  1207. return GetAsLocalizedTime(use12hourclock ? "h" : "HH", false);
  1208. case TIME_FORMAT_HH_SS:
  1209. return GetAsLocalizedTime(use12hourclock ? "h:ss" : "HH:ss", true);
  1210. case TIME_FORMAT_HH_MM:
  1211. return GetAsLocalizedTime(use12hourclock ? "h:mm" : "HH:mm", false);
  1212. case TIME_FORMAT_HH_MM_XX:
  1213. return GetAsLocalizedTime(use12hourclock ? "h:mm xx" : "HH:mm", false);
  1214. case TIME_FORMAT_HH_MM_SS:
  1215. return GetAsLocalizedTime(use12hourclock ? "hh:mm:ss" : "HH:mm:ss", true);
  1216. case TIME_FORMAT_HH_MM_SS_XX:
  1217. return GetAsLocalizedTime(use12hourclock ? "hh:mm:ss xx" : "HH:mm:ss", true);
  1218. case TIME_FORMAT_H:
  1219. return GetAsLocalizedTime("h", false);
  1220. case TIME_FORMAT_M:
  1221. return GetAsLocalizedTime("m", false);
  1222. case TIME_FORMAT_H_MM_SS:
  1223. return GetAsLocalizedTime("h:mm:ss", true);
  1224. case TIME_FORMAT_H_MM_SS_XX:
  1225. return GetAsLocalizedTime("h:mm:ss xx", true);
  1226. case TIME_FORMAT_XX:
  1227. return use12hourclock ? GetAsLocalizedTime("xx", false) : "";
  1228. default:
  1229. break;
  1230. }
  1231. return GetAsLocalizedTime("", false);
  1232. }
  1233. CDateTime CDateTime::GetAsUTCDateTime() const
  1234. {
  1235. CDateTime time(m_time);
  1236. time += GetTimezoneBias();
  1237. return time;
  1238. }
  1239. std::string CDateTime::GetAsRFC1123DateTime() const
  1240. {
  1241. CDateTime time(GetAsUTCDateTime());
  1242. int weekDay = time.GetDayOfWeek();
  1243. if (weekDay < 0)
  1244. weekDay = 0;
  1245. else if (weekDay > 6)
  1246. weekDay = 6;
  1247. if (weekDay != time.GetDayOfWeek())
  1248. CLog::Log(LOGWARNING, "Invalid day of week %d in %s", time.GetDayOfWeek(), time.GetAsDBDateTime().c_str());
  1249. int month = time.GetMonth();
  1250. if (month < 1)
  1251. month = 1;
  1252. else if (month > 12)
  1253. month = 12;
  1254. if (month != time.GetMonth())
  1255. CLog::Log(LOGWARNING, "Invalid month %d in %s", time.GetMonth(), time.GetAsDBDateTime().c_str());
  1256. return 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());
  1257. }
  1258. std::string CDateTime::GetAsW3CDate() const
  1259. {
  1260. KODI::TIME::SystemTime st;
  1261. GetAsSystemTime(st);
  1262. return StringUtils::Format("%04i-%02i-%02i", st.year, st.month, st.day);
  1263. }
  1264. std::string CDateTime::GetAsW3CDateTime(bool asUtc /* = false */) const
  1265. {
  1266. CDateTime w3cDate = *this;
  1267. if (asUtc)
  1268. w3cDate = GetAsUTCDateTime();
  1269. KODI::TIME::SystemTime st;
  1270. w3cDate.GetAsSystemTime(st);
  1271. std::string result = StringUtils::Format("%04i-%02i-%02iT%02i:%02i:%02i", st.year, st.month,
  1272. st.day, st.hour, st.minute, st.second);
  1273. if (asUtc)
  1274. return result + "Z";
  1275. CDateTimeSpan bias = GetTimezoneBias();
  1276. return result + StringUtils::Format("%c%02i:%02i", (bias.GetSecondsTotal() >= 0 ? '+' : '-'), abs(bias.GetHours()), abs(bias.GetMinutes())).c_str();
  1277. }
  1278. int CDateTime::MonthStringToMonthNum(const std::string& month)
  1279. {
  1280. const char* months[] = {"january","february","march","april","may","june","july","august","september","october","november","december"};
  1281. const char* abr_months[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
  1282. int i = 0;
  1283. for (; i < 12 && !StringUtils::EqualsNoCase(month, months[i]) && !StringUtils::EqualsNoCase(month, abr_months[i]); i++);
  1284. i++;
  1285. return i;
  1286. }