1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
6 #include "mozilla/Sprintf.h"
7 #include "nsILocaleService.h"
8 #include "nsDateTimeFormatCID.h"
9 #include "nsIDateTimeFormat.h"
10 #include "nsIScriptableDateFormat.h"
11 #include "nsCOMPtr.h"
12 #include "nsServiceManagerUtils.h"
13
14 static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID);
15 static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
16
17 class nsScriptableDateFormat : public nsIScriptableDateFormat {
18 public:
19 NS_DECL_ISUPPORTS
20
21 NS_IMETHOD FormatDateTime(const char16_t *locale,
22 nsDateFormatSelector dateFormatSelector,
23 nsTimeFormatSelector timeFormatSelector,
24 int32_t year,
25 int32_t month,
26 int32_t day,
27 int32_t hour,
28 int32_t minute,
29 int32_t second,
30 char16_t **dateTimeString) override;
31
FormatDate(const char16_t * locale,nsDateFormatSelector dateFormatSelector,int32_t year,int32_t month,int32_t day,char16_t ** dateString)32 NS_IMETHOD FormatDate(const char16_t *locale,
33 nsDateFormatSelector dateFormatSelector,
34 int32_t year,
35 int32_t month,
36 int32_t day,
37 char16_t **dateString) override
38 {return FormatDateTime(locale, dateFormatSelector, kTimeFormatNone,
39 year, month, day, 0, 0, 0, dateString);}
40
FormatTime(const char16_t * locale,nsTimeFormatSelector timeFormatSelector,int32_t hour,int32_t minute,int32_t second,char16_t ** timeString)41 NS_IMETHOD FormatTime(const char16_t *locale,
42 nsTimeFormatSelector timeFormatSelector,
43 int32_t hour,
44 int32_t minute,
45 int32_t second,
46 char16_t **timeString) override
47 {return FormatDateTime(locale, kDateFormatNone, timeFormatSelector,
48 1999, 1, 1, hour, minute, second, timeString);}
49
nsScriptableDateFormat()50 nsScriptableDateFormat() {}
51
52 private:
53 nsString mStringOut;
54
~nsScriptableDateFormat()55 virtual ~nsScriptableDateFormat() {}
56 };
57
NS_IMPL_ISUPPORTS(nsScriptableDateFormat,nsIScriptableDateFormat)58 NS_IMPL_ISUPPORTS(nsScriptableDateFormat, nsIScriptableDateFormat)
59
60 NS_IMETHODIMP nsScriptableDateFormat::FormatDateTime(
61 const char16_t *aLocale,
62 nsDateFormatSelector dateFormatSelector,
63 nsTimeFormatSelector timeFormatSelector,
64 int32_t year,
65 int32_t month,
66 int32_t day,
67 int32_t hour,
68 int32_t minute,
69 int32_t second,
70 char16_t **dateTimeString)
71 {
72 // We can't have a valid date with the year, month or day
73 // being lower than 1.
74 if (year < 1 || month < 1 || day < 1)
75 return NS_ERROR_INVALID_ARG;
76
77 nsresult rv;
78 nsAutoString localeName(aLocale);
79 *dateTimeString = nullptr;
80
81 nsCOMPtr<nsILocale> locale;
82 // re-initialise locale pointer only if the locale was given explicitly
83 if (!localeName.IsEmpty()) {
84 // get locale service
85 nsCOMPtr<nsILocaleService> localeService(do_GetService(kLocaleServiceCID, &rv));
86 NS_ENSURE_SUCCESS(rv, rv);
87 // get locale
88 rv = localeService->NewLocale(localeName, getter_AddRefs(locale));
89 NS_ENSURE_SUCCESS(rv, rv);
90 }
91
92 nsCOMPtr<nsIDateTimeFormat> dateTimeFormat(do_CreateInstance(kDateTimeFormatCID, &rv));
93 NS_ENSURE_SUCCESS(rv, rv);
94
95 tm tmTime;
96 time_t timetTime;
97
98 memset(&tmTime, 0, sizeof(tmTime));
99 tmTime.tm_year = year - 1900;
100 tmTime.tm_mon = month - 1;
101 tmTime.tm_mday = day;
102 tmTime.tm_hour = hour;
103 tmTime.tm_min = minute;
104 tmTime.tm_sec = second;
105 tmTime.tm_yday = tmTime.tm_wday = 0;
106 tmTime.tm_isdst = -1;
107 timetTime = mktime(&tmTime);
108
109 if ((time_t)-1 != timetTime) {
110 rv = dateTimeFormat->FormatTime(locale, dateFormatSelector, timeFormatSelector,
111 timetTime, mStringOut);
112 }
113 else {
114 // if mktime fails (e.g. year <= 1970), then try NSPR.
115 PRTime prtime;
116 char string[32];
117 SprintfLiteral(string, "%.2d/%.2d/%d %.2d:%.2d:%.2d", month, day, year, hour, minute, second);
118 if (PR_SUCCESS != PR_ParseTimeString(string, false, &prtime))
119 return NS_ERROR_INVALID_ARG;
120
121 rv = dateTimeFormat->FormatPRTime(locale, dateFormatSelector, timeFormatSelector,
122 prtime, mStringOut);
123 }
124 if (NS_SUCCEEDED(rv))
125 *dateTimeString = ToNewUnicode(mStringOut);
126
127 return rv;
128 }
129
130 nsresult
NS_NewScriptableDateFormat(nsISupports * aOuter,REFNSIID aIID,void ** aResult)131 NS_NewScriptableDateFormat(nsISupports* aOuter, REFNSIID aIID, void** aResult)
132 {
133 if (aOuter)
134 return NS_ERROR_NO_AGGREGATION;
135
136 nsScriptableDateFormat* result = new nsScriptableDateFormat();
137 if (! result)
138 return NS_ERROR_OUT_OF_MEMORY;
139
140 NS_ADDREF(result);
141 nsresult rv = result->QueryInterface(aIID, aResult);
142 NS_RELEASE(result);
143
144 return rv;
145 }
146