| /* |
| * Copyright (C) 2012 Google Inc. |
| * Licensed to The Android Open Source Project. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.mail; |
| |
| import android.content.Context; |
| import android.text.format.DateUtils; |
| |
| import java.util.Calendar; |
| import java.util.Formatter; |
| |
| /** |
| * Convenience class to efficiently make multiple short date strings. Instantiating and reusing |
| * one of these builders is faster than repeatedly bringing up all the locale stuff. |
| * |
| */ |
| public class FormattedDateBuilder { |
| |
| private final StringBuilder sb; |
| private final Formatter dateFormatter; |
| private final Context mContext; |
| |
| public FormattedDateBuilder(Context context) { |
| mContext = context; |
| sb = new StringBuilder(); |
| dateFormatter = new Formatter(sb); |
| } |
| |
| /** |
| * 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 formatDateTime(when, DateUtils.FORMAT_SHOW_TIME); |
| } else if (isCurrentYear(when)) { |
| return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH); |
| } else { |
| return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE); |
| } |
| } |
| |
| /** |
| * 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 getRelativeDateTimeString(mContext, when, DateUtils.DAY_IN_MILLIS, |
| 2 * DateUtils.WEEK_IN_MILLIS, |
| DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH); |
| } else { |
| return formatDateTime(when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE); |
| } |
| } |
| |
| /** |
| * 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 |
| */ |
| public CharSequence formatFullDateTime(long when) { |
| sb.setLength(0); |
| DateUtils.formatDateRange(mContext, dateFormatter, when, when, |
| DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | |
| DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_ALL); |
| return sb.toString(); |
| } |
| |
| /** |
| * 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)); |
| } |
| |
| 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 CharSequence formatDateTime(long when, int flags) { |
| sb.setLength(0); |
| DateUtils.formatDateRange(mContext, dateFormatter, when, when, flags); |
| return sb.toString(); |
| } |
| |
| /** |
| * A port of |
| * {@link DateUtils#getRelativeDateTimeString(android.content.Context, long, long, long, int)} |
| * that does not include the time in strings like "2 days ago". |
| */ |
| private static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution, |
| long transitionResolution, int flags) { |
| final long now = System.currentTimeMillis(); |
| final long duration = Math.abs(now - time); |
| |
| // getRelativeTimeSpanString() doesn't correctly format relative dates |
| // above a week or exact dates below a day, so clamp |
| // transitionResolution as needed. |
| if (transitionResolution > DateUtils.WEEK_IN_MILLIS) { |
| transitionResolution = DateUtils.WEEK_IN_MILLIS; |
| } else if (transitionResolution < DateUtils.DAY_IN_MILLIS) { |
| transitionResolution = DateUtils.DAY_IN_MILLIS; |
| } |
| |
| if (duration < transitionResolution) { |
| return DateUtils.getRelativeTimeSpanString(time, now, minResolution, flags); |
| } else { |
| return DateUtils.getRelativeTimeSpanString(c, time, false); |
| } |
| } |
| } |