Bug 653261 - Add a function to format the date and time displayed in the Download Manager. r=sdwilsh sr=mconnor
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Wed, 27 Jul 2011 13:08:24 +0200
changeset 73397 69913a1505dfca87506c910636a98a749d294d90
parent 73396 e6ce4fc82ffc96d742afcb7aa28869da98dd5b14
child 73419 6c9c2e013decc70308333fae23caed5a8ead945f
push id810
push userdgottwald@mozilla.com
push dateWed, 27 Jul 2011 11:09:13 +0000
treeherdermozilla-inbound@69913a1505df [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssdwilsh, mconnor
bugs653261
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 653261 - Add a function to format the date and time displayed in the Download Manager. r=sdwilsh sr=mconnor
toolkit/mozapps/downloads/DownloadUtils.jsm
toolkit/mozapps/downloads/content/downloads.js
toolkit/mozapps/downloads/tests/unit/test_DownloadUtils.js
--- a/toolkit/mozapps/downloads/DownloadUtils.jsm
+++ b/toolkit/mozapps/downloads/DownloadUtils.jsm
@@ -48,16 +48,19 @@ var EXPORTED_SYMBOLS = [ "DownloadUtils"
  *                   [optional] double aSpeed, [optional] double aLastSec)
  *
  * string progress
  * getTransferTotal(int aCurrBytes, [optional] int aMaxBytes)
  *
  * [string timeLeft, double newLast]
  * getTimeLeft(double aSeconds, [optional] double aLastSec)
  *
+ * [string dateCompact, string dateComplete]
+ * getReadableDates(Date aDate, [optional] Date aNow)
+ *
  * [string displayHost, string fullHost]
  * getURIHost(string aURIString)
  *
  * [string convertedBytes, string units]
  * convertByteUnits(int aBytes)
  *
  * [int time, string units, int subTime, string subUnits]
  * convertTimeUnits(double aSecs)
@@ -88,16 +91,18 @@ let kStrings = {
   transferSameUnits: "transferSameUnits",
   transferDiffUnits: "transferDiffUnits",
   transferNoTotal: "transferNoTotal",
   timePair: "timePair",
   timeLeftSingle: "timeLeftSingle",
   timeLeftDouble: "timeLeftDouble",
   timeFewSeconds: "timeFewSeconds",
   timeUnknown: "timeUnknown",
+  monthDate: "monthDate",
+  yesterday: "yesterday",
   doneScheme: "doneScheme",
   doneFileScheme: "doneFileScheme",
   units: ["bytes", "kilobyte", "megabyte", "gigabyte"],
   // Update timeSize in convertTimeUnits if changing the length of this array
   timeUnits: ["seconds", "minutes", "hours", "days"],
 };
 
 // This object will lazily load the strings defined in kStrings
@@ -316,16 +321,81 @@ let DownloadUtils = {
         timeLeft = replaceInsert(timeLeft, 2, pair2);
       }
     }
 
     return [timeLeft, aSeconds];
   },
 
   /**
+   * Converts a Date object to two readable formats, one compact, one complete.
+   * The compact format is relative to the current date, and is not an accurate
+   * representation. For example, only the time is displayed for today. The
+   * complete format always includes both the date and the time, excluding the
+   * seconds, and is often shown when hovering the cursor over the compact
+   * representation.
+   *
+   * @param aDate
+   *        Date object representing the date and time to format. It is assumed
+   *        that this value represents a past date.
+   * @param [optional] aNow
+   *        Date object representing the current date and time. The real date
+   *        and time of invocation is used if this parameter is omitted.
+   * @return A pair: [compact text, complete text]
+   */
+  getReadableDates: function DU_getReadableDates(aDate, aNow)
+  {
+    if (!aNow) {
+      aNow = new Date();
+    }
+
+    let dts = Cc["@mozilla.org/intl/scriptabledateformat;1"]
+              .getService(Ci.nsIScriptableDateFormat);
+
+    // Figure out when today begins
+    let today = new Date(aNow.getFullYear(), aNow.getMonth(), aNow.getDate());
+
+    // Figure out if the time is from today, yesterday, this week, etc.
+    let dateTimeCompact;
+    if (aDate >= today) {
+      // After today started, show the time
+      dateTimeCompact = dts.FormatTime("",
+                                       dts.timeFormatNoSeconds,
+                                       aDate.getHours(),
+                                       aDate.getMinutes(),
+                                       0);
+    } else if (today - aDate < (24 * 60 * 60 * 1000)) {
+      // After yesterday started, show yesterday
+      dateTimeCompact = gStr.yesterday;
+    } else if (today - aDate < (6 * 24 * 60 * 60 * 1000)) {
+      // After last week started, show day of week
+      dateTimeCompact = aDate.toLocaleFormat("%A");
+    } else {
+      // Show month/day
+      let month = aDate.toLocaleFormat("%B");
+      // Remove leading 0 by converting the date string to a number
+      let date = Number(aDate.toLocaleFormat("%d"));
+      dateTimeCompact = replaceInsert(gStr.monthDate, 1, month);
+      dateTimeCompact = replaceInsert(dateTimeCompact, 2, date);
+    }
+
+    let dateTimeFull = dts.FormatDateTime("",
+                                          dts.dateFormatLong,
+                                          dts.timeFormatNoSeconds,
+                                          aDate.getFullYear(),
+                                          aDate.getMonth() + 1,
+                                          aDate.getDate(),
+                                          aDate.getHours(),
+                                          aDate.getMinutes(),
+                                          0);
+
+    return [dateTimeCompact, dateTimeFull];
+  },
+
+  /**
    * Get the appropriate display host string for a URI string depending on if
    * the URI has an eTLD + 1, is an IP address, a local file, or other protocol
    *
    * @param aURIString
    *        The URI string to try getting an eTLD + 1, etc.
    * @return A pair: [display host for the URI string, full host name]
    */
   getURIHost: function DU_getURIHost(aURIString)
--- a/toolkit/mozapps/downloads/content/downloads.js
+++ b/toolkit/mozapps/downloads/content/downloads.js
@@ -106,18 +106,16 @@ let gStr = {
   doneStatus: "doneStatus",
   doneSize: "doneSize",
   doneSizeUnknown: "doneSizeUnknown",
   stateFailed: "stateFailed",
   stateCanceled: "stateCanceled",
   stateBlockedParentalControls: "stateBlocked",
   stateBlockedPolicy: "stateBlockedPolicy",
   stateDirty: "stateDirty",
-  yesterday: "yesterday",
-  monthDate: "monthDate",
   downloadsTitleFiles: "downloadsTitleFiles",
   downloadsTitlePercent: "downloadsTitlePercent",
   fileExecutableSecurityWarningTitle: "fileExecutableSecurityWarningTitle",
   fileExecutableSecurityWarningDontAsk: "fileExecutableSecurityWarningDontAsk"
 };
 
 // The statement to query for downloads that are active or match the search
 let gStmt = null;
@@ -1047,61 +1045,20 @@ function updateStatus(aItem, aDownload) 
  *        The richlistitem representing a download in the UI
  */
 function updateTime(aItem)
 {
   // Don't bother updating for things that aren't finished
   if (aItem.inProgress)
     return;
 
-  let dts = Cc["@mozilla.org/intl/scriptabledateformat;1"].
-            getService(Ci.nsIScriptableDateFormat);
-
-  // Figure out when today begins
-  let now = new Date();
-  let today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
-
-  // Get the end time to display
   let end = new Date(parseInt(aItem.getAttribute("endTime")));
-
-  // Figure out if the end time is from today, yesterday, this week, etc.
-  let dateTime;
-  if (end >= today) {
-    // Download finished after today started, show the time
-    dateTime = dts.FormatTime("", dts.timeFormatNoSeconds,
-                              end.getHours(), end.getMinutes(), 0);
-  } else if (today - end < (24 * 60 * 60 * 1000)) {
-    // Download finished after yesterday started, show yesterday
-    dateTime = gStr.yesterday;
-  } else if (today - end < (6 * 24 * 60 * 60 * 1000)) {
-    // Download finished after last week started, show day of week
-    dateTime = end.toLocaleFormat("%A");
-  } else {
-    // Download must have been from some time ago.. show month/day
-    let month = end.toLocaleFormat("%B");
-    // Remove leading 0 by converting the date string to a number
-    let date = Number(end.toLocaleFormat("%d"));
-    dateTime = replaceInsert(gStr.monthDate, 1, month);
-    dateTime = replaceInsert(dateTime, 2, date);
-  }
-
-  aItem.setAttribute("dateTime", dateTime);
-
-  // Set the tooltip to be the full date and time
-  let dateTimeTip = dts.FormatDateTime("",
-                                       dts.dateFormatLong,
-                                       dts.timeFormatNoSeconds,
-                                       end.getFullYear(),
-                                       end.getMonth() + 1,
-                                       end.getDate(),
-                                       end.getHours(),
-                                       end.getMinutes(),
-                                       0); 
-
-  aItem.setAttribute("dateTimeTip", dateTimeTip);
+  let [dateCompact, dateComplete] = DownloadUtils.getReadableDates(end);
+  aItem.setAttribute("dateTime", dateCompact);
+  aItem.setAttribute("dateTimeTip", dateComplete);
 }
 
 /**
  * Helper function to replace a placeholder string with a real string
  *
  * @param aText
  *        Source text containing placeholder (e.g., #1)
  * @param aIndex
--- a/toolkit/mozapps/downloads/tests/unit/test_DownloadUtils.js
+++ b/toolkit/mozapps/downloads/tests/unit/test_DownloadUtils.js
@@ -91,16 +91,57 @@ function testURI(aURI, aDisp, aHost)
 
   let [disp, host] = DownloadUtils.getURIHost(aURI);
 
   // Make sure we have the right display host and full host
   do_check_eq(disp, aDisp);
   do_check_eq(host, aHost);
 }
 
+
+function testGetReadableDates(aDate, aCompactValue)
+{
+  const now = new Date(2000, 11, 31, 11, 59, 59);
+
+  let [dateCompact] = DownloadUtils.getReadableDates(aDate, now);
+  do_check_eq(dateCompact, aCompactValue);
+}
+
+function testAllGetReadableDates()
+{
+  // This test cannot depend on the current date and time, or the date format.
+  // It depends on being run with the English localization, however.
+  const today_11_30     = new Date(2000, 11, 31, 11, 30, 15);
+  const today_12_30     = new Date(2000, 11, 31, 12, 30, 15);
+  const yesterday_11_30 = new Date(2000, 11, 30, 11, 30, 15);
+  const yesterday_12_30 = new Date(2000, 11, 30, 12, 30, 15);
+  const twodaysago      = new Date(2000, 11, 29, 11, 30, 15);
+  const sixdaysago      = new Date(2000, 11, 25, 11, 30, 15);
+  const sevendaysago    = new Date(2000, 11, 24, 11, 30, 15);
+
+  let dts = Components.classes["@mozilla.org/intl/scriptabledateformat;1"].
+            getService(Components.interfaces.nsIScriptableDateFormat);
+
+  testGetReadableDates(today_11_30, dts.FormatTime("", dts.timeFormatNoSeconds,
+                                                   11, 30, 0));
+  testGetReadableDates(today_12_30, dts.FormatTime("", dts.timeFormatNoSeconds,
+                                                   12, 30, 0));
+  testGetReadableDates(yesterday_11_30, "Yesterday");
+  testGetReadableDates(yesterday_12_30, "Yesterday");
+  testGetReadableDates(twodaysago, twodaysago.toLocaleFormat("%A"));
+  testGetReadableDates(sixdaysago, sixdaysago.toLocaleFormat("%A"));
+  testGetReadableDates(sevendaysago, sevendaysago.toLocaleFormat("%B") + " " +
+                                     sevendaysago.toLocaleFormat("%d"));
+
+  let [, dateTimeFull] = DownloadUtils.getReadableDates(today_11_30);
+  do_check_eq(dateTimeFull, dts.FormatDateTime("", dts.dateFormatLong,
+                                                   dts.timeFormatNoSeconds,
+                                                   2000, 12, 31, 11, 30, 0));
+}
+
 function run_test()
 {
   testConvertByteUnits(-1, "-1", "bytes");
   testConvertByteUnits(1, _("1"), "bytes");
   testConvertByteUnits(42, _("42"), "bytes");
   testConvertByteUnits(123, _("123"), "bytes");
   testConvertByteUnits(1024, _("1.0"), "KB");
   testConvertByteUnits(8888, _("8.7"), "KB");
@@ -158,9 +199,11 @@ function run_test()
 
   testURI("http://www.mozilla.org/", "mozilla.org", "www.mozilla.org");
   testURI("http://www.city.mikasa.hokkaido.jp/", "city.mikasa.hokkaido.jp", "www.city.mikasa.hokkaido.jp");
   testURI("data:text/html,Hello World", "data resource", "data resource");
   testURI("jar:http://www.mozilla.com/file!/magic", "mozilla.com", "www.mozilla.com");
   testURI("file:///C:/Cool/Stuff/", "local file", "local file");
   testURI("moz-icon:file:///test.extension", "moz-icon resource", "moz-icon resource");
   testURI("about:config", "about resource", "about resource");
+
+  testAllGetReadableDates();
 }