Update date format

This is according to the new android date format rules.

Change-Id: I3d6ca4579ddd3ecb63a6f67e88fb00545fe0ffaa
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ebb1176..e472dee 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -862,14 +862,8 @@
     <!-- Action bar title for viewing messages that are attached to another message. -->
     <string name="attached_message">Attached message</string>
 
-    <!-- Shown to display the date of the message [CHAR LIMIT=50] -->
-    <string name="date_message_received"><xliff:g id="day_and_date">%1$s</xliff:g>, <xliff:g id="time">%2$s</xliff:g></string>
-
-    <!-- Shown to display the date of the message when the message was received today. [CHAR LIMIT=50] -->
-    <string name="date_message_received_today">Today, <xliff:g id="time">%1$s</xliff:g></string>
-
-    <!-- Shown to display the date of the message when the message was received yesterday. [CHAR LIMIT=50] -->
-    <string name="date_message_received_yesterday">Yesterday, <xliff:g id="time">%1$s</xliff:g></string>
+    <!-- Shown to display the date of the message when the message was received yesterday. [CHAR LIMIT=50]  -->
+    <string name="date_message_received_yesterday">Yesterday, <xliff:g id="datetime">%1$s</xliff:g></string>
 
     <!-- Content description for the "X" image icon for dismissing a tip. This is used for spoken description of the icon when touch explore is enabled. [CHAR LIMIT=50] -->
     <string name="dismiss_tip_hover_text">Dismiss tip</string>
diff --git a/src/com/android/mail/FormattedDateBuilder.java b/src/com/android/mail/FormattedDateBuilder.java
index d7c17b2..d93c3a5 100644
--- a/src/com/android/mail/FormattedDateBuilder.java
+++ b/src/com/android/mail/FormattedDateBuilder.java
@@ -17,11 +17,13 @@
 package com.android.mail;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.text.format.DateUtils;
-import android.text.format.Time;
 
+import com.android.mail.R;
+
+import java.util.Calendar;
 import java.util.Formatter;
+import java.util.GregorianCalendar;
 
 /**
  * Convenience class to efficiently make multiple short date strings. Instantiating and reusing
@@ -30,9 +32,9 @@
  */
 public class FormattedDateBuilder {
 
-    private StringBuilder sb;
-    private Formatter dateFormatter;
-    private Context mContext;
+    private final StringBuilder sb;
+    private final Formatter dateFormatter;
+    private final Context mContext;
 
     public FormattedDateBuilder(Context context) {
         mContext = context;
@@ -40,53 +42,109 @@
         dateFormatter = new Formatter(sb);
     }
 
-    public CharSequence formatShortDate(long when) {
-        return DateUtils.getRelativeTimeSpanString(mContext, when);
-    }
-
-    public CharSequence formatLongDateTime(long when) {
-        final Resources resources = mContext.getResources();
-
+    /**
+     * This is used in the conversation list, and headers of collapsed messages in
+     * threaded conversations.
+     * Times on today's date will just display time, e.g. 8:15 AM
+     * Times not today, but within the same calendar year will display absolute date, e.g. Nov 6
+     * Times not in the same year display a numeric absolute date, e.g. 11/18/12
+     *
+     * @param when The time to generate a formatted date for
+     * @return The formatted date
+     */
+    public CharSequence formatShortDateTime(long when) {
         if (DateUtils.isToday(when)) {
-            return resources.getString(R.string.date_message_received_today, formatLongTime(when));
-        } else if (isYesterday(when)) {
-            return resources.getString(
-                    R.string.date_message_received_yesterday, formatLongTime(when));
+            return formatDateTime(when, DateUtils.FORMAT_SHOW_TIME);
+        } else if (isCurrentYear(when)) {
+            return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH);
         } else {
-            return resources.getString(R.string.date_message_received,
-                    formatLongDayAndDate(when), formatLongTime(when));
+            return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE);
         }
     }
 
-    public CharSequence formatLongDayAndDate(long when) {
-        sb.setLength(0);
-        DateUtils.formatDateRange(mContext, dateFormatter, when, when,
-                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY
-                        | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_ALL);
-        return sb.toString();
-    }
-
-    public CharSequence formatLongTime(long when) {
-        sb.setLength(0);
-        DateUtils.formatDateRange(mContext, dateFormatter, when, when,
-                DateUtils.FORMAT_SHOW_TIME);
-        return sb.toString();
+    /**
+     * This is used in regular message headers.
+     * Times on today's date will just display time, e.g. 8:15 AM
+     * Times not today, but within two weeks ago will display relative date and time,
+     * e.g. 6 days ago, 8:15 AM
+     * Times more than two weeks ago but within the same calendar year will display
+     * absolute date and time, e.g. Nov 6, 8:15 AM
+     * Times not in the same year display a numeric absolute date, e.g. 11/18/12
+     *
+     * @param when The time to generate a formatted date for
+     * @return The formatted date
+     */
+    public CharSequence formatLongDateTime(long when) {
+        if (DateUtils.isToday(when)) {
+            return formatDateTime(when, DateUtils.FORMAT_SHOW_TIME);
+        } else if (isCurrentYear(when)) {
+            return DateUtils.getRelativeDateTimeString(mContext, when, DateUtils.DAY_IN_MILLIS,
+                    2 * DateUtils.WEEK_IN_MILLIS,
+                    DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
+                    DateUtils.FORMAT_ABBREV_MONTH);
+        } else {
+            return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE);
+        }
     }
 
     /**
-     * @return true if the supplied when is today else false
+     * This is used in expanded details headers.
+     * Displays full date and time e.g. Tue, Nov 18, 2012, 8:15 AM, or
+     * Yesterday, Nov 18, 2012, 8:15 AM
+     *
+     * @param when The time to generate a formatted date for
+     * @return The formatted date
      */
-    private static boolean isYesterday(long when) {
-        final Time time = new Time();
-        time.set(when);
+    public CharSequence formatFullDateTime(long when) {
+        sb.setLength(0);
+        if (isYesterday(when)) {
+            DateUtils.formatDateRange(mContext, dateFormatter, when, when,
+                    DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
+                    DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_ALL);
+            return mContext.getString(R.string.date_message_received_yesterday, sb.toString());
+        } else {
+            DateUtils.formatDateRange(mContext, dateFormatter, when, when,
+                    DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
+                    DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_YEAR |
+                    DateUtils.FORMAT_ABBREV_ALL);
+            return sb.toString();
+        }
+    }
 
-        final int thenYear = time.year;
-        final int thenMonth = time.month;
-        final int thenMonthDay = time.monthDay;
+    /**
+     * This is used for displaying dates when printing.
+     * Displays the full date, e.g. Tue, Nov 18, 2012 at 8:15 PM
+     *
+     * @param when The time to generate a formatted date for
+     * @return The formatted date
+     */
+    public String formatDateTimeForPrinting(long when) {
+        return mContext.getString(R.string.date_message_received_print,
+                formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
+                        DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_ALL),
+                        formatDateTime(when, DateUtils.FORMAT_SHOW_TIME));
+    }
 
-        time.set(System.currentTimeMillis());
-        return (thenYear == time.year)
-                && (thenMonth == time.month)
-                && (thenMonthDay == (time.monthDay-1));
+    private boolean isCurrentYear(long when) {
+        final Calendar nowCal = Calendar.getInstance();
+        final Calendar whenCal = Calendar.getInstance();
+        whenCal.setTimeInMillis(when);
+        return (nowCal.get(Calendar.YEAR) == whenCal.get(Calendar.YEAR));
+    }
+
+    private boolean isYesterday(long when) {
+        final Calendar nowCal = Calendar.getInstance();
+        final Calendar whenCal = Calendar.getInstance();
+        whenCal.setTimeInMillis(when);
+        // Decrement the "now" calendar back one day, and see if both are now the same day.
+        nowCal.add(Calendar.DAY_OF_YEAR, -1);
+        return (whenCal.get(Calendar.DAY_OF_YEAR) == nowCal.get(Calendar.DAY_OF_YEAR) &&
+                whenCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR));
+    }
+
+    private CharSequence formatDateTime(long when, int flags) {
+        sb.setLength(0);
+        DateUtils.formatDateRange(mContext, dateFormatter, when, when, flags);
+        return sb.toString();
     }
 }
diff --git a/src/com/android/mail/browse/ConversationViewAdapter.java b/src/com/android/mail/browse/ConversationViewAdapter.java
index ed05786..8406531 100644
--- a/src/com/android/mail/browse/ConversationViewAdapter.java
+++ b/src/com/android/mail/browse/ConversationViewAdapter.java
@@ -57,16 +57,16 @@
  */
 public class ConversationViewAdapter extends BaseAdapter {
 
-    private Context mContext;
+    private final Context mContext;
     private final FormattedDateBuilder mDateBuilder;
     private final ConversationAccountController mAccountController;
     private final LoaderManager mLoaderManager;
     private final FragmentManager mFragmentManager;
     private final MessageHeaderViewCallbacks mMessageCallbacks;
     private final ContactInfoSource mContactInfoSource;
-    private ConversationViewHeaderCallbacks mConversationCallbacks;
-    private OnClickListener mSuperCollapsedListener;
-    private Map<String, Address> mAddressCache;
+    private final ConversationViewHeaderCallbacks mConversationCallbacks;
+    private final OnClickListener mSuperCollapsedListener;
+    private final Map<String, Address> mAddressCache;
     private final LayoutInflater mInflater;
 
     private final List<ConversationOverlayItem> mItems;
@@ -135,8 +135,9 @@
         // cached values to speed up re-rendering during view recycling
         private CharSequence mTimestampShort;
         private CharSequence mTimestampLong;
+        private CharSequence mTimestampFull;
         private long mTimestampMs;
-        private FormattedDateBuilder mDateBuilder;
+        private final FormattedDateBuilder mDateBuilder;
         public CharSequence recipientSummaryText;
 
         MessageHeaderItem(ConversationViewAdapter adapter, FormattedDateBuilder dateBuilder,
@@ -237,11 +238,17 @@
             return mTimestampLong;
         }
 
+        public CharSequence getTimestampFull() {
+            ensureTimestamps();
+            return mTimestampFull;
+        }
+
         private void ensureTimestamps() {
             if (mMessage.dateReceivedMs != mTimestampMs) {
                 mTimestampMs = mMessage.dateReceivedMs;
-                mTimestampShort = mDateBuilder.formatShortDate(mTimestampMs);
+                mTimestampShort = mDateBuilder.formatShortDateTime(mTimestampMs);
                 mTimestampLong = mDateBuilder.formatLongDateTime(mTimestampMs);
+                mTimestampFull = mDateBuilder.formatFullDateTime(mTimestampMs);
             }
         }
 
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index c4e1341..db4faef 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -1288,7 +1288,7 @@
         if (!mExpandedDetailsValid) {
             renderExpandedDetails(getResources(), mExpandedDetailsView, mMessage.viaDomain,
                     mAddressCache, getAccount(), mVeiledMatcher, mFrom, mReplyTo, mTo, mCc, mBcc,
-                    mMessageHeaderItem.getTimestampLong());
+                    mMessageHeaderItem.getTimestampFull());
 
             mExpandedDetailsValid = true;
         }
diff --git a/src/com/android/mail/print/PrintUtils.java b/src/com/android/mail/print/PrintUtils.java
index ec83d25..2d387c3 100644
--- a/src/com/android/mail/print/PrintUtils.java
+++ b/src/com/android/mail/print/PrintUtils.java
@@ -158,9 +158,7 @@
             HtmlPrintTemplates templates, FormattedDateBuilder dateBuilder) {
         final Address fromAddress = Utils.getAddress(addressCache, message.getFrom());
         final long when = message.dateReceivedMs;
-        final String date = res.getString(R.string.date_message_received_print,
-                dateBuilder.formatLongDayAndDate(when), dateBuilder.formatLongTime(when));
-
+        final String date = dateBuilder.formatDateTimeForPrinting(when);
 
         templates.appendMessage(fromAddress.getName(), fromAddress.getAddress(), date,
                 renderRecipients(res, addressCache, message), message.getBodyAsHtml(),