TimeUtil.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include "TimeUtil.h"
  19. namespace KC {
  20. /**
  21. * Get a timestamp for the given date/time point
  22. *
  23. * Gets a timestamp for 'Nth [weekday] in month X, year Y at HH:00:00 GMT'
  24. *
  25. * @param year Full year (eg 2008, 2010)
  26. * @param month Month 1-12
  27. * @param week Week 1-5 (1 == first, 2 == second, 5 == last)
  28. * @param day Day 0-6 (0 == sunday, 1 == monday, ...)
  29. * @param hour Hour 0-23 (0 == 00:00, 1 == 01:00, ...)
  30. */
  31. time_t getDateByYearMonthWeekDayHour(WORD year, WORD month, WORD week, WORD day, WORD hour)
  32. {
  33. struct tm tm = {0};
  34. time_t date;
  35. // get first day of month
  36. tm.tm_year = year;
  37. tm.tm_mon = month-1;
  38. tm.tm_mday = 1;
  39. date = timegm(&tm);
  40. // convert back to struct to get wday info
  41. gmtime_safe(&date, &tm);
  42. date -= tm.tm_wday * 24 * 60 * 60; // back up to start of week
  43. date += week * 7 * 24 * 60 * 60; // go to correct week nr
  44. date += day * 24 * 60 * 60;
  45. date += hour * 60 * 60;
  46. // if we are in the next month, then back up a week, because week '5' means
  47. // 'last week of month'
  48. gmtime_safe(&date, &tm);
  49. if (tm.tm_mon != month-1)
  50. date -= 7 * 24 * 60 * 60;
  51. return date;
  52. }
  53. LONG getTZOffset(time_t date, TIMEZONE_STRUCT sTimeZone)
  54. {
  55. struct tm tm;
  56. time_t dststart, dstend;
  57. bool dst = false;
  58. if (sTimeZone.lStdBias == sTimeZone.lDstBias || sTimeZone.stDstDate.wMonth == 0 || sTimeZone.stStdDate.wMonth == 0)
  59. return -(sTimeZone.lBias) * 60;
  60. gmtime_safe(&date, &tm);
  61. dststart = getDateByYearMonthWeekDayHour(tm.tm_year, sTimeZone.stDstDate.wMonth, sTimeZone.stDstDate.wDay, sTimeZone.stDstDate.wDayOfWeek, sTimeZone.stDstDate.wHour);
  62. dstend = getDateByYearMonthWeekDayHour(tm.tm_year, sTimeZone.stStdDate.wMonth, sTimeZone.stStdDate.wDay, sTimeZone.stStdDate.wDayOfWeek, sTimeZone.stStdDate.wHour);
  63. if (dststart <= dstend) {
  64. // Northern hemisphere, eg DST is during Mar-Oct
  65. if (date > dststart && date < dstend)
  66. dst = true;
  67. } else {
  68. // Southern hemisphere, eg DST is during Oct-Mar
  69. if (date < dstend || date > dststart)
  70. dst = true;
  71. }
  72. if (dst)
  73. return -(sTimeZone.lBias + sTimeZone.lDstBias) * 60;
  74. return -(sTimeZone.lBias + sTimeZone.lStdBias) * 60;
  75. }
  76. time_t UTCToLocal(time_t utc, TIMEZONE_STRUCT sTimeZone)
  77. {
  78. return utc + getTZOffset(utc, sTimeZone);
  79. }
  80. time_t LocalToUTC(time_t local, TIMEZONE_STRUCT sTimeZone)
  81. {
  82. return local - getTZOffset(local, sTimeZone);
  83. }
  84. } /* namespace */