nsDateTimeFormatWin.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsDateTimeFormatWin.h"
  6. #include "nsIServiceManager.h"
  7. #include "nsIComponentManager.h"
  8. #include "nsILocaleService.h"
  9. #include "nsWin32Locale.h"
  10. #include "nsUnicharUtils.h"
  11. #include "nsCRT.h"
  12. #include "nsCOMPtr.h"
  13. #define NSDATETIMEFORMAT_BUFFER_LEN 80
  14. NS_IMPL_ISUPPORTS(nsDateTimeFormatWin, nsIDateTimeFormat)
  15. // init this interface to a specified locale
  16. nsresult nsDateTimeFormatWin::Initialize(nsILocale* locale)
  17. {
  18. nsAutoString localeStr;
  19. nsresult res = NS_OK;
  20. // use cached info if match with stored locale
  21. if (!locale) {
  22. if (!mLocale.IsEmpty() &&
  23. mLocale.Equals(mAppLocale, nsCaseInsensitiveStringComparator())) {
  24. return NS_OK;
  25. }
  26. }
  27. else {
  28. res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr);
  29. if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
  30. if (!mLocale.IsEmpty() &&
  31. mLocale.Equals(localeStr, nsCaseInsensitiveStringComparator())) {
  32. return NS_OK;
  33. }
  34. }
  35. }
  36. // default LCID (en-US)
  37. mLCID = 1033;
  38. // get locale string, use app default if no locale specified
  39. if (!locale) {
  40. nsCOMPtr<nsILocaleService> localeService =
  41. do_GetService(NS_LOCALESERVICE_CONTRACTID);
  42. if (localeService) {
  43. nsCOMPtr<nsILocale> appLocale;
  44. res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
  45. if (NS_SUCCEEDED(res)) {
  46. res = appLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"),
  47. localeStr);
  48. if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
  49. mAppLocale.Assign(localeStr); // cache app locale name
  50. }
  51. }
  52. }
  53. }
  54. else {
  55. res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr);
  56. }
  57. // Get LCID and charset name from locale, if available
  58. if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
  59. mLocale.Assign(localeStr); // cache locale name
  60. res = nsWin32Locale::GetPlatformLocale(mLocale, (LCID *) &mLCID);
  61. }
  62. return res;
  63. }
  64. // performs a locale sensitive date formatting operation on the time_t parameter
  65. nsresult nsDateTimeFormatWin::FormatTime(nsILocale* locale,
  66. const nsDateFormatSelector dateFormatSelector,
  67. const nsTimeFormatSelector timeFormatSelector,
  68. const time_t timetTime,
  69. nsAString& stringOut)
  70. {
  71. return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, localtime( &timetTime ), stringOut);
  72. }
  73. // performs a locale sensitive date formatting operation on the struct tm parameter
  74. nsresult nsDateTimeFormatWin::FormatTMTime(nsILocale* locale,
  75. const nsDateFormatSelector dateFormatSelector,
  76. const nsTimeFormatSelector timeFormatSelector,
  77. const struct tm* tmTime,
  78. nsAString& stringOut)
  79. {
  80. SYSTEMTIME system_time;
  81. DWORD dwFlags_Date = 0, dwFlags_Time = 0;
  82. int dateLen, timeLen;
  83. char16_t dateBuffer[NSDATETIMEFORMAT_BUFFER_LEN], timeBuffer[NSDATETIMEFORMAT_BUFFER_LEN];
  84. // set up locale data
  85. (void) Initialize(locale);
  86. // Map tm to SYSTEMTIME
  87. system_time.wYear = 1900 + tmTime->tm_year;
  88. system_time.wMonth = tmTime->tm_mon + 1;
  89. system_time.wDayOfWeek = tmTime->tm_wday;
  90. system_time.wDay = tmTime->tm_mday;
  91. system_time.wHour = tmTime->tm_hour;
  92. system_time.wMinute = tmTime->tm_min;
  93. system_time.wSecond = tmTime->tm_sec;
  94. system_time.wMilliseconds = 0;
  95. // Map to WinAPI date format
  96. switch (dateFormatSelector) {
  97. case kDateFormatLong:
  98. dwFlags_Date = DATE_LONGDATE;
  99. break;
  100. case kDateFormatShort:
  101. dwFlags_Date = DATE_SHORTDATE;
  102. break;
  103. case kDateFormatWeekday:
  104. dwFlags_Date = 0;
  105. break;
  106. case kDateFormatYearMonth:
  107. dwFlags_Date = 0; // TODO:only availabe NT5
  108. break;
  109. }
  110. // Map to WinAPI time format
  111. switch (timeFormatSelector) {
  112. case kTimeFormatSeconds:
  113. dwFlags_Time = 0;
  114. break;
  115. case kTimeFormatNoSeconds:
  116. dwFlags_Time = TIME_NOSECONDS;
  117. break;
  118. case kTimeFormatSecondsForce24Hour:
  119. dwFlags_Time = TIME_FORCE24HOURFORMAT;
  120. break;
  121. case kTimeFormatNoSecondsForce24Hour:
  122. dwFlags_Time = TIME_NOSECONDS + TIME_FORCE24HOURFORMAT;
  123. break;
  124. }
  125. // Call GetDateFormatW
  126. if (dateFormatSelector == kDateFormatNone) {
  127. dateLen = 0;
  128. }
  129. else {
  130. if (dateFormatSelector == kDateFormatYearMonth) {
  131. dateLen = nsGetDateFormatW(0, &system_time, "yyyy/MM",
  132. dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
  133. }
  134. else if (dateFormatSelector == kDateFormatWeekday) {
  135. dateLen = nsGetDateFormatW(0, &system_time, "ddd",
  136. dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
  137. }
  138. else {
  139. dateLen = nsGetDateFormatW(dwFlags_Date, &system_time, nullptr,
  140. dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
  141. }
  142. if (dateLen != 0) {
  143. dateLen--; // Since the count includes the terminating null.
  144. }
  145. }
  146. // Call GetTimeFormatW
  147. if (timeFormatSelector == kTimeFormatNone) {
  148. timeLen = 0;
  149. }
  150. else {
  151. timeLen = nsGetTimeFormatW(dwFlags_Time, &system_time, nullptr,
  152. timeBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
  153. if (timeLen != 0) {
  154. timeLen--; // Since the count includes the terminating null.
  155. }
  156. }
  157. NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (dateLen + 1), "internal date buffer is not large enough");
  158. NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (timeLen + 1), "internal time buffer is not large enough");
  159. // Copy the result
  160. stringOut.Truncate();
  161. if (dateLen != 0 && timeLen != 0) {
  162. stringOut.Assign(dateBuffer, dateLen);
  163. stringOut.Append((char16_t *)(L" "), 1);
  164. stringOut.Append(timeBuffer, timeLen);
  165. }
  166. else if (dateLen != 0 && timeLen == 0) {
  167. stringOut.Assign(dateBuffer, dateLen);
  168. }
  169. else if (dateLen == 0 && timeLen != 0) {
  170. stringOut.Assign(timeBuffer, timeLen);
  171. }
  172. return NS_OK;
  173. }
  174. // performs a locale sensitive date formatting operation on the PRTime parameter
  175. nsresult nsDateTimeFormatWin::FormatPRTime(nsILocale* locale,
  176. const nsDateFormatSelector dateFormatSelector,
  177. const nsTimeFormatSelector timeFormatSelector,
  178. const PRTime prTime,
  179. nsAString& stringOut)
  180. {
  181. PRExplodedTime explodedTime;
  182. PR_ExplodeTime(prTime, PR_LocalTimeParameters, &explodedTime);
  183. return FormatPRExplodedTime(locale, dateFormatSelector, timeFormatSelector, &explodedTime, stringOut);
  184. }
  185. // performs a locale sensitive date formatting operation on the PRExplodedTime parameter
  186. nsresult nsDateTimeFormatWin::FormatPRExplodedTime(nsILocale* locale,
  187. const nsDateFormatSelector dateFormatSelector,
  188. const nsTimeFormatSelector timeFormatSelector,
  189. const PRExplodedTime* explodedTime,
  190. nsAString& stringOut)
  191. {
  192. struct tm tmTime;
  193. memset( &tmTime, 0, sizeof(tmTime) );
  194. tmTime.tm_yday = explodedTime->tm_yday;
  195. tmTime.tm_wday = explodedTime->tm_wday;
  196. tmTime.tm_year = explodedTime->tm_year;
  197. tmTime.tm_year -= 1900;
  198. tmTime.tm_mon = explodedTime->tm_month;
  199. tmTime.tm_mday = explodedTime->tm_mday;
  200. tmTime.tm_hour = explodedTime->tm_hour;
  201. tmTime.tm_min = explodedTime->tm_min;
  202. tmTime.tm_sec = explodedTime->tm_sec;
  203. return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, &tmTime, stringOut);
  204. }
  205. int nsDateTimeFormatWin::nsGetTimeFormatW(DWORD dwFlags, const SYSTEMTIME *lpTime,
  206. const char* format, char16_t *timeStr, int cchTime)
  207. {
  208. int len = 0;
  209. len = GetTimeFormatW(mLCID, dwFlags, lpTime,
  210. format ?
  211. NS_ConvertASCIItoUTF16(format).get() :
  212. nullptr,
  213. (LPWSTR) timeStr, cchTime);
  214. return len;
  215. }
  216. int nsDateTimeFormatWin::nsGetDateFormatW(DWORD dwFlags, const SYSTEMTIME *lpDate,
  217. const char* format, char16_t *dateStr, int cchDate)
  218. {
  219. int len = 0;
  220. len = GetDateFormatW(mLCID, dwFlags, lpDate,
  221. format ? NS_ConvertASCIItoUTF16(format).get() : nullptr,
  222. (LPWSTR) dateStr, cchDate);
  223. return len;
  224. }