PageRenderTime 134ms CodeModel.GetById 12ms app.highlight 111ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/XBDateTime.cpp

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