Bug 1343766 - Add DateTimeFomat without ICU for Android. r=emk a=gchang
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Fri, 10 Mar 2017 12:58:21 +0900
changeset 395124 8acbaea575e2bc8c14bdeb251a040f1290b8b240
parent 395123 e8fdbc7507a7fbae31399ea4dcc173f65f9abe36
child 395125 bf077c4f7cb2bd2e3517364bc5ebb9d0417ef5b3
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemk, gchang
bugs1343766
milestone54.0a2
Bug 1343766 - Add DateTimeFomat without ICU for Android. r=emk a=gchang MozReview-Commit-ID: FWeBliqlXv3
intl/locale/DateTimeFormat.h
intl/locale/DateTimeFormatAndroid.cpp
intl/locale/moz.build
--- a/intl/locale/DateTimeFormat.h
+++ b/intl/locale/DateTimeFormat.h
@@ -7,17 +7,19 @@
 #ifndef mozilla_DateTimeFormat_h
 #define mozilla_DateTimeFormat_h
 
 #include <time.h>
 #include "gtest/MozGtestFriend.h"
 #include "nsIScriptableDateFormat.h"
 #include "nsStringGlue.h"
 #include "prtime.h"
+#ifdef ENABLE_INTL_API
 #include "unicode/udat.h"
+#endif
 
 namespace mozilla {
 
 class DateTimeFormat {
 public:
   // performs a locale sensitive date formatting operation on the time_t parameter
   static nsresult FormatTime(const nsDateFormatSelector aDateFormatSelector,
                              const nsTimeFormatSelector aTimeFormatSelector,
@@ -41,21 +43,23 @@ public:
 private:
   DateTimeFormat() = delete;
 
   static nsresult Initialize();
 
   FRIEND_TEST(DateTimeFormat, FormatPRExplodedTime);
   FRIEND_TEST(DateTimeFormat, DateFormatSelectors);
 
+#ifdef ENABLE_INTL_API
   // performs a locale sensitive date formatting operation on the UDate parameter
   static nsresult FormatUDateTime(const nsDateFormatSelector aDateFormatSelector,
                                   const nsTimeFormatSelector aTimeFormatSelector,
                                   const UDate aUDateTime,
                                   const PRTimeParameters* aTimeParameters,
                                   nsAString& aStringOut);
+#endif
 
   static nsCString* mLocale;
 };
 
 }
 
 #endif  /* mozilla_DateTimeFormat_h */
new file mode 100644
--- /dev/null
+++ b/intl/locale/DateTimeFormatAndroid.cpp
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DateTimeFormat.h"
+#include "prtime.h"
+
+#include <time.h>
+
+#define NSDATETIME_FORMAT_BUFFER_LEN 80
+
+namespace mozilla {
+
+nsCString* DateTimeFormat::mLocale = nullptr;
+
+// performs a locale sensitive date formatting operation on the struct tm
+// parameter
+
+static nsresult
+FormatTMTime(const nsDateFormatSelector aDateFormatSelector,
+             const nsTimeFormatSelector aTimeFormatSelector,
+             const struct tm* aTmTime,
+             nsAString& aStringOut)
+{
+  // set date format
+  nsAutoCString format;
+  if (aDateFormatSelector == kDateFormatLong &&
+      aTimeFormatSelector == kTimeFormatSeconds) {
+    format.AssignLiteral("%c");
+  } else {
+    switch (aDateFormatSelector) {
+      case kDateFormatLong:
+      case kDateFormatShort:
+        format.AssignLiteral("%x");
+        break;
+      case kDateFormatWeekday:
+        format.AssignLiteral("%a");
+        break;
+      case kDateFormatMonthLong:
+        format.AssignLiteral("%B");
+        break;
+      case kDateFormatYearMonth:
+        format.AssignLiteral("%m/%Y");
+        break;
+      case kDateFormatYearMonthLong:
+        format.AssignLiteral("%B %Y");
+        break;
+      case kDateFormatNone:
+      default:
+        break;
+    }
+
+    // set time format
+    switch (aTimeFormatSelector) {
+      case kTimeFormatSeconds:
+        if (!format.IsEmpty()) {
+          format.AppendLiteral(" ");
+        }
+        format.AppendLiteral("%X");
+        break;
+      case kTimeFormatNoSeconds:
+        if (!format.IsEmpty()) {
+          format.AppendLiteral(" ");
+        }
+        format.AppendLiteral("%H:%M");
+        break;
+      case kTimeFormatNone:
+      default:
+        break;
+    }
+  }
+
+  // generate date/time string
+  char strOut[NSDATETIME_FORMAT_BUFFER_LEN];
+  if (!format.IsEmpty()) {
+    strftime(strOut, NSDATETIME_FORMAT_BUFFER_LEN, format.get(), aTmTime);
+    CopyUTF8toUTF16(strOut, aStringOut);
+  } else {
+    aStringOut.Truncate();
+  }
+
+  return NS_OK;
+}
+
+/*static*/ nsresult
+DateTimeFormat::FormatTime(const nsDateFormatSelector aDateFormatSelector,
+                           const nsTimeFormatSelector aTimeFormatSelector,
+                           const time_t aTimetTime,
+                           nsAString& aStringOut)
+{
+  struct tm tmTime;
+  memcpy(&tmTime, localtime(&aTimetTime), sizeof(struct tm));
+  return FormatTMTime(
+    aDateFormatSelector, aTimeFormatSelector, &tmTime, aStringOut);
+}
+
+// performs a locale sensitive date formatting operation on the PRTime parameter
+
+// static
+nsresult
+DateTimeFormat::FormatPRTime(const nsDateFormatSelector aDateFormatSelector,
+                             const nsTimeFormatSelector aTimeFormatSelector,
+                             const PRTime aPrTime,
+                             nsAString& aStringOut)
+{
+  PRExplodedTime explodedTime;
+  PR_ExplodeTime(aPrTime, PR_LocalTimeParameters, &explodedTime);
+
+  return FormatPRExplodedTime(
+    aDateFormatSelector, aTimeFormatSelector, &explodedTime, aStringOut);
+}
+
+// performs a locale sensitive date formatting operation on the PRExplodedTime
+// parameter
+// static
+nsresult
+DateTimeFormat::FormatPRExplodedTime(
+  const nsDateFormatSelector aDateFormatSelector,
+  const nsTimeFormatSelector aTimeFormatSelector,
+  const PRExplodedTime* aExplodedTime,
+  nsAString& aStringOut)
+{
+  struct tm tmTime;
+  /* be safe and set all members of struct tm to zero
+   *
+   * there are other fields in the tm struct that we aren't setting
+   * (tm_isdst, tm_gmtoff, tm_zone, should we set these?) and since
+   * tmTime is on the stack, it may be filled with garbage, but
+   * the garbage may vary.  (this may explain why some saw bug #10412, and
+   * others did not.
+   *
+   * when tmTime is passed to strftime() with garbage bad things may happen.
+   * see bug #10412
+   */
+  memset(&tmTime, 0, sizeof(tmTime));
+
+  tmTime.tm_yday = aExplodedTime->tm_yday;
+  tmTime.tm_wday = aExplodedTime->tm_wday;
+  tmTime.tm_year = aExplodedTime->tm_year;
+  tmTime.tm_year -= 1900;
+  tmTime.tm_mon = aExplodedTime->tm_month;
+  tmTime.tm_mday = aExplodedTime->tm_mday;
+  tmTime.tm_hour = aExplodedTime->tm_hour;
+  tmTime.tm_min = aExplodedTime->tm_min;
+  tmTime.tm_sec = aExplodedTime->tm_sec;
+
+  return FormatTMTime(
+    aDateFormatSelector, aTimeFormatSelector, &tmTime, aStringOut);
+}
+
+// static
+void
+DateTimeFormat::Shutdown()
+{
+}
+
+} // namespace mozilla
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -40,27 +40,35 @@ EXPORTS += [
 ]
 
 EXPORTS.mozilla.intl += [
     'LocaleService.h',
     'OSPreferences.h',
 ]
 
 UNIFIED_SOURCES += [
-    'DateTimeFormat.cpp',
     'LocaleService.cpp',
     'nsCollation.cpp',
     'nsLanguageAtomService.cpp',
     'nsLocale.cpp',
     'nsLocaleService.cpp',
     'nsScriptableDateFormat.cpp',
     'nsUConvPropertySearch.cpp',
     'OSPreferences.cpp',
 ]
 
+if CONFIG['ENABLE_INTL_API']:
+    UNIFIED_SOURCES += [
+        'DateTimeFormat.cpp',
+    ]
+else:
+    UNIFIED_SOURCES += [
+        'DateTimeFormatAndroid.cpp',
+    ]
+
 EXTRA_JS_MODULES += [
     'PluralForm.jsm',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/intl/uconv',