1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/locale/src/windows/nsDateTimeFormatWin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsDateTimeFormatWin.h" 1.10 +#include "nsIServiceManager.h" 1.11 +#include "nsIComponentManager.h" 1.12 +#include "nsILocaleService.h" 1.13 +#include "nsWin32Locale.h" 1.14 +#include "nsUnicharUtils.h" 1.15 +#include "nsCRT.h" 1.16 +#include "nsCOMPtr.h" 1.17 + 1.18 + 1.19 +#define NSDATETIMEFORMAT_BUFFER_LEN 80 1.20 + 1.21 +NS_IMPL_ISUPPORTS(nsDateTimeFormatWin, nsIDateTimeFormat) 1.22 + 1.23 + 1.24 +// init this interface to a specified locale 1.25 +nsresult nsDateTimeFormatWin::Initialize(nsILocale* locale) 1.26 +{ 1.27 + nsAutoString localeStr; 1.28 + nsresult res = NS_OK; 1.29 + 1.30 + // use cached info if match with stored locale 1.31 + if (!locale) { 1.32 + if (!mLocale.IsEmpty() && 1.33 + mLocale.Equals(mAppLocale, nsCaseInsensitiveStringComparator())) { 1.34 + return NS_OK; 1.35 + } 1.36 + } 1.37 + else { 1.38 + res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr); 1.39 + if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) { 1.40 + if (!mLocale.IsEmpty() && 1.41 + mLocale.Equals(localeStr, nsCaseInsensitiveStringComparator())) { 1.42 + return NS_OK; 1.43 + } 1.44 + } 1.45 + } 1.46 + 1.47 + // default LCID (en-US) 1.48 + mLCID = 1033; 1.49 + 1.50 + // get locale string, use app default if no locale specified 1.51 + if (!locale) { 1.52 + nsCOMPtr<nsILocaleService> localeService = 1.53 + do_GetService(NS_LOCALESERVICE_CONTRACTID); 1.54 + if (localeService) { 1.55 + nsCOMPtr<nsILocale> appLocale; 1.56 + res = localeService->GetApplicationLocale(getter_AddRefs(appLocale)); 1.57 + if (NS_SUCCEEDED(res)) { 1.58 + res = appLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), 1.59 + localeStr); 1.60 + if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) { 1.61 + mAppLocale.Assign(localeStr); // cache app locale name 1.62 + } 1.63 + } 1.64 + } 1.65 + } 1.66 + else { 1.67 + res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr); 1.68 + } 1.69 + 1.70 + // Get LCID and charset name from locale, if available 1.71 + if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) { 1.72 + mLocale.Assign(localeStr); // cache locale name 1.73 + res = nsWin32Locale::GetPlatformLocale(mLocale, (LCID *) &mLCID); 1.74 + } 1.75 + 1.76 + return res; 1.77 +} 1.78 + 1.79 +// performs a locale sensitive date formatting operation on the time_t parameter 1.80 +nsresult nsDateTimeFormatWin::FormatTime(nsILocale* locale, 1.81 + const nsDateFormatSelector dateFormatSelector, 1.82 + const nsTimeFormatSelector timeFormatSelector, 1.83 + const time_t timetTime, 1.84 + nsAString& stringOut) 1.85 +{ 1.86 + return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, localtime( &timetTime ), stringOut); 1.87 +} 1.88 + 1.89 +// performs a locale sensitive date formatting operation on the struct tm parameter 1.90 +nsresult nsDateTimeFormatWin::FormatTMTime(nsILocale* locale, 1.91 + const nsDateFormatSelector dateFormatSelector, 1.92 + const nsTimeFormatSelector timeFormatSelector, 1.93 + const struct tm* tmTime, 1.94 + nsAString& stringOut) 1.95 +{ 1.96 + SYSTEMTIME system_time; 1.97 + DWORD dwFlags_Date = 0, dwFlags_Time = 0; 1.98 + int dateLen, timeLen; 1.99 + char16_t dateBuffer[NSDATETIMEFORMAT_BUFFER_LEN], timeBuffer[NSDATETIMEFORMAT_BUFFER_LEN]; 1.100 + 1.101 + // set up locale data 1.102 + (void) Initialize(locale); 1.103 + 1.104 + // Map tm to SYSTEMTIME 1.105 + system_time.wYear = 1900 + tmTime->tm_year; 1.106 + system_time.wMonth = tmTime->tm_mon + 1; 1.107 + system_time.wDayOfWeek = tmTime->tm_wday; 1.108 + system_time.wDay = tmTime->tm_mday; 1.109 + system_time.wHour = tmTime->tm_hour; 1.110 + system_time.wMinute = tmTime->tm_min; 1.111 + system_time.wSecond = tmTime->tm_sec; 1.112 + system_time.wMilliseconds = 0; 1.113 + 1.114 + // Map to WinAPI date format 1.115 + switch (dateFormatSelector) { 1.116 + case kDateFormatLong: 1.117 + dwFlags_Date = DATE_LONGDATE; 1.118 + break; 1.119 + case kDateFormatShort: 1.120 + dwFlags_Date = DATE_SHORTDATE; 1.121 + break; 1.122 + case kDateFormatWeekday: 1.123 + dwFlags_Date = 0; 1.124 + break; 1.125 + case kDateFormatYearMonth: 1.126 + dwFlags_Date = 0; // TODO:only availabe NT5 1.127 + break; 1.128 + } 1.129 + 1.130 + // Map to WinAPI time format 1.131 + switch (timeFormatSelector) { 1.132 + case kTimeFormatSeconds: 1.133 + dwFlags_Time = 0; 1.134 + break; 1.135 + case kTimeFormatNoSeconds: 1.136 + dwFlags_Time = TIME_NOSECONDS; 1.137 + break; 1.138 + case kTimeFormatSecondsForce24Hour: 1.139 + dwFlags_Time = TIME_FORCE24HOURFORMAT; 1.140 + break; 1.141 + case kTimeFormatNoSecondsForce24Hour: 1.142 + dwFlags_Time = TIME_NOSECONDS + TIME_FORCE24HOURFORMAT; 1.143 + break; 1.144 + } 1.145 + 1.146 + // Call GetDateFormatW 1.147 + if (dateFormatSelector == kDateFormatNone) { 1.148 + dateLen = 0; 1.149 + } 1.150 + else { 1.151 + if (dateFormatSelector == kDateFormatYearMonth) { 1.152 + dateLen = nsGetDateFormatW(0, &system_time, "yyyy/MM", 1.153 + dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN); 1.154 + } 1.155 + else if (dateFormatSelector == kDateFormatWeekday) { 1.156 + dateLen = nsGetDateFormatW(0, &system_time, "ddd", 1.157 + dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN); 1.158 + } 1.159 + else { 1.160 + dateLen = nsGetDateFormatW(dwFlags_Date, &system_time, nullptr, 1.161 + dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN); 1.162 + } 1.163 + if (dateLen != 0) { 1.164 + dateLen--; // Since the count includes the terminating null. 1.165 + } 1.166 + } 1.167 + 1.168 + // Call GetTimeFormatW 1.169 + if (timeFormatSelector == kTimeFormatNone) { 1.170 + timeLen = 0; 1.171 + } 1.172 + else { 1.173 + timeLen = nsGetTimeFormatW(dwFlags_Time, &system_time, nullptr, 1.174 + timeBuffer, NSDATETIMEFORMAT_BUFFER_LEN); 1.175 + if (timeLen != 0) { 1.176 + timeLen--; // Since the count includes the terminating null. 1.177 + } 1.178 + } 1.179 + 1.180 + NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (dateLen + 1), "internal date buffer is not large enough"); 1.181 + NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (timeLen + 1), "internal time buffer is not large enough"); 1.182 + 1.183 + // Copy the result 1.184 + stringOut.Truncate(); 1.185 + if (dateLen != 0 && timeLen != 0) { 1.186 + stringOut.Assign(dateBuffer, dateLen); 1.187 + stringOut.Append((char16_t *)(L" "), 1); 1.188 + stringOut.Append(timeBuffer, timeLen); 1.189 + } 1.190 + else if (dateLen != 0 && timeLen == 0) { 1.191 + stringOut.Assign(dateBuffer, dateLen); 1.192 + } 1.193 + else if (dateLen == 0 && timeLen != 0) { 1.194 + stringOut.Assign(timeBuffer, timeLen); 1.195 + } 1.196 + 1.197 + return NS_OK; 1.198 +} 1.199 + 1.200 +// performs a locale sensitive date formatting operation on the PRTime parameter 1.201 +nsresult nsDateTimeFormatWin::FormatPRTime(nsILocale* locale, 1.202 + const nsDateFormatSelector dateFormatSelector, 1.203 + const nsTimeFormatSelector timeFormatSelector, 1.204 + const PRTime prTime, 1.205 + nsAString& stringOut) 1.206 +{ 1.207 + PRExplodedTime explodedTime; 1.208 + PR_ExplodeTime(prTime, PR_LocalTimeParameters, &explodedTime); 1.209 + 1.210 + return FormatPRExplodedTime(locale, dateFormatSelector, timeFormatSelector, &explodedTime, stringOut); 1.211 +} 1.212 + 1.213 +// performs a locale sensitive date formatting operation on the PRExplodedTime parameter 1.214 +nsresult nsDateTimeFormatWin::FormatPRExplodedTime(nsILocale* locale, 1.215 + const nsDateFormatSelector dateFormatSelector, 1.216 + const nsTimeFormatSelector timeFormatSelector, 1.217 + const PRExplodedTime* explodedTime, 1.218 + nsAString& stringOut) 1.219 +{ 1.220 + struct tm tmTime; 1.221 + memset( &tmTime, 0, sizeof(tmTime) ); 1.222 + 1.223 + tmTime.tm_yday = explodedTime->tm_yday; 1.224 + tmTime.tm_wday = explodedTime->tm_wday; 1.225 + tmTime.tm_year = explodedTime->tm_year; 1.226 + tmTime.tm_year -= 1900; 1.227 + tmTime.tm_mon = explodedTime->tm_month; 1.228 + tmTime.tm_mday = explodedTime->tm_mday; 1.229 + tmTime.tm_hour = explodedTime->tm_hour; 1.230 + tmTime.tm_min = explodedTime->tm_min; 1.231 + tmTime.tm_sec = explodedTime->tm_sec; 1.232 + 1.233 + return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, &tmTime, stringOut); 1.234 +} 1.235 + 1.236 +int nsDateTimeFormatWin::nsGetTimeFormatW(DWORD dwFlags, const SYSTEMTIME *lpTime, 1.237 + const char* format, char16_t *timeStr, int cchTime) 1.238 +{ 1.239 + int len = 0; 1.240 + len = GetTimeFormatW(mLCID, dwFlags, lpTime, 1.241 + format ? 1.242 + NS_ConvertASCIItoUTF16(format).get() : 1.243 + nullptr, 1.244 + (LPWSTR) timeStr, cchTime); 1.245 + return len; 1.246 +} 1.247 + 1.248 +int nsDateTimeFormatWin::nsGetDateFormatW(DWORD dwFlags, const SYSTEMTIME *lpDate, 1.249 + const char* format, char16_t *dateStr, int cchDate) 1.250 +{ 1.251 + int len = 0; 1.252 + len = GetDateFormatW(mLCID, dwFlags, lpDate, 1.253 + format ? NS_ConvertASCIItoUTF16(format).get() : nullptr, 1.254 + (LPWSTR) dateStr, cchDate); 1.255 + return len; 1.256 +}