All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yy.androidlib.util.prettytime.PrettyTime Maven / Gradle / Ivy

There is a newer version: 1.0.5
Show newest version
/*
 * Copyright 2012 Lincoln Baxter, III
 * 
 * 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.yy.androidlib.util.prettytime;

import com.yy.androidlib.util.prettytime.impl.DurationImpl;
import com.yy.androidlib.util.prettytime.impl.ResourcesTimeFormat;
import com.yy.androidlib.util.prettytime.impl.ResourcesTimeUnit;
import com.yy.androidlib.util.prettytime.units.*;

import java.util.*;

/**
 * A utility for creating social-networking style timestamps. (e.g. "just now", "moments ago", "3 days ago",
 * "within 2 months")
 * 

* Usage: *

* * PrettyTime t = new PrettyTime();
* String timestamp = t.format(new Date());
* //result: moments from now *

* * * @author localUnits = getUnits(); DurationImpl result = new DurationImpl(); for (int i = 0; i < localUnits.size(); i++) { TimeUnit unit = localUnits.get(i); long millisPerUnit = Math.abs(unit.getMillisPerUnit()); long quantity = Math.abs(unit.getMaxQuantity()); boolean isLastUnit = (i == localUnits.size() - 1); if ((0 == quantity) && !isLastUnit) { quantity = localUnits.get(i + 1).getMillisPerUnit() / unit.getMillisPerUnit(); } // does our unit encompass the time duration? if ((millisPerUnit * quantity > absoluteDifference) || isLastUnit) { result.setUnit(unit); if (millisPerUnit > absoluteDifference) { // we are rounding up: get 1 or -1 for past or future result.setQuantity(getSign(difference)); result.setDelta(0); } else { result.setQuantity(difference / millisPerUnit); result.setDelta(difference - result.getQuantity() * millisPerUnit); } break; } } return result; } private long getSign(final long difference) { if (0 > difference) { return -1; } else { return 1; } } /** * Calculate to the precision of the smallest provided {@link TimeUnit}, the exact duration represented by the * difference between the reference timestamp, and {@code then} *

* Note: Precision may be lost if no supplied {@link TimeUnit} is granular enough to represent one millisecond * * @param then The date to be compared against the reference timestamp, or now if no reference timestamp was * provided * @return A sorted {@link java.util.List} of {@link Duration} objects, from largest to smallest. Each element in the list * represents the approximate duration (number of times) that {@link TimeUnit} to fit into the previous * element's delta. The first element is the largest {@link TimeUnit} to fit within the total difference * between compared dates. */ public List calculatePreciseDuration(final Date then) { if (then == null) { throw new IllegalArgumentException("Date to calculate must not be null."); } if (null == reference) { reference = new Date(); } List result = new ArrayList(); long difference = then.getTime() - reference.getTime(); Duration duration = calculateDuration(difference); result.add(duration); while (0 != duration.getDelta()) { duration = calculateDuration(duration.getDelta()); result.add(duration); } return result; } /** * Format the given {@link java.util.Date} object. This method applies the {@code PrettyTime.approximateDuration(date)} method * to perform its calculation. If {@code then} is null, it will default to {@code new Date()}; also decorate for * past/future tense. * * @param duration the {@link java.util.Date} to be formatted * @return A formatted string representing {@code then} */ public String format(Date then) { if (then == null) { throw new IllegalArgumentException("Date to format must not be null."); } Duration d = approximateDuration(then); return format(d); } /** * Format the given {@link java.util.Calendar} object. This method applies the {@code PrettyTime.approximateDuration(date)} method * to perform its calculation. If {@code then} is null, it will default to {@code new Date()}; also decorate for * past/future tense. * * @param duration the {@link java.util.Calendar} whose date is to be formatted * @return A formatted string representing {@code then} */ public String format(Calendar then) { if (then == null) { throw new IllegalArgumentException("Provided Calendar must not be null."); } return format(then.getTime()); } /** * Format the given {@link java.util.Date} object. This method applies the {@code PrettyTime.approximateDuration(date)} method * to perform its calculation. If {@code then} is null, it will default to {@code new Date()}; also decorate for * past/future tense. Rounding rules are ignored. * * @param duration the {@link java.util.Date} to be formatted * @return A formatted string representing {@code then} */ public String formatUnrounded(Date then) { if (then == null) { throw new IllegalArgumentException("Date to format must not be null."); } Duration d = approximateDuration(then); return formatUnrounded(d); } /** * Format the given {@link Duration} object, using the {@link TimeFormat} specified by the {@link TimeUnit} contained * within; also decorate for past/future tense. * * @param duration the {@link Duration} to be formatted * @return A formatted string representing {@code duration} */ public String format(final Duration duration) { if (duration == null) { throw new IllegalArgumentException("Duration to format must not be null."); } TimeFormat format = getFormat(duration.getUnit()); String time = format.format(duration); return format.decorate(duration, time); } /** * Format the given {@link Duration} object, using the {@link TimeFormat} specified by the {@link TimeUnit} contained * within; also decorate for past/future tense. Rounding rules are ignored. * * @param duration the {@link Duration} to be formatted * @return A formatted string representing {@code duration} */ public String formatUnrounded(Duration duration) { if (duration == null) { throw new IllegalArgumentException("Duration to format must not be null."); } TimeFormat format = getFormat(duration.getUnit()); String time = format.formatUnrounded(duration); return format.decorateUnrounded(duration, time); } /** * Format the given {@link Duration} objects, using the {@link TimeFormat} specified by the {@link TimeUnit} * contained within. Rounds only the last {@link Duration} object. * * @param durations the {@link Duration}s to be formatted * @return A list of formatted strings representing {@code durations} */ public String format(final List durations) { if (durations == null) { throw new IllegalArgumentException("Duration list must not be null."); } StringBuilder builder = new StringBuilder(); Duration duration = null; TimeFormat format = null; for (int i = 0; i < durations.size(); i++) { duration = durations.get(i); format = getFormat(duration.getUnit()); boolean isLast = (i == durations.size() - 1); if (!isLast) { builder.append(format.formatUnrounded(duration)); } else { builder.append(format.format(duration)); } } if (format != null) { return format.decorateUnrounded(duration, builder.toString()); } else { return ""; } } /** * Given a date, returns a non-relative format string for the * approximate duration of the difference between the date and now. * * @param date the date to be formatted * @return A formatted string of the approximate duration */ public String formatApproximateDuration(Date date) { Duration duration = approximateDuration(date); return formatDuration(duration); } /** * Given a duration, returns a non-relative format string. * * @param duration the duration to be formatted * @return A formatted string of the duration */ public String formatDuration(Duration duration) { TimeFormat timeFormat = getFormat(duration.getUnit()); return timeFormat.format(duration); } /** * Get the registered {@link TimeFormat} for the given {@link TimeUnit} or null if none exists. */ public TimeFormat getFormat(TimeUnit unit) { if (unit == null) { throw new IllegalArgumentException("Time unit must not be null."); } if (units.get(unit) != null) { return units.get(unit); } return null; } /** * Get the current reference timestamp. *

* See {@code PrettyTime.setReference(Date timestamp)} * * @return */ public Date getReference() { return reference; } /** * Set the reference timestamp. *

* If the Date formatted is before the reference timestamp, the format command will produce a String that is in the * past tense. If the Date formatted is after the reference timestamp, the format command will produce a string that * is in the future tense. */ public PrettyTime setReference(final Date timestamp) { reference = timestamp; return this; } /** * Get a {@link java.util.List} of the current configured {@link TimeUnit} instances in calculations. * * @return */ public List getUnits() { if (mCachedUnits == null) { List result = new ArrayList(units.keySet()); Collections.sort(result, new TimeUnitComparator()); mCachedUnits = Collections.unmodifiableList(result); } return mCachedUnits; } /** * Get the registered {@link TimeUnit} for the given {@link TimeUnit} type or null if none exists. * * @return */ @SuppressWarnings("unchecked") public UNIT getUnit(final Class unitType) { if (unitType == null) { throw new IllegalArgumentException("Unit type to get must not be null."); } for (TimeUnit unit : units.keySet()) { if (unitType.isAssignableFrom(unit.getClass())) { return (UNIT) unit; } } return null; } /** * Register the given {@link TimeUnit} and corresponding {@link TimeFormat} instance to be used in calculations. If * an entry already exists for the given {@link TimeUnit}, its format will be overwritten with the given * {@link TimeFormat}. */ public PrettyTime registerUnit(final TimeUnit unit, TimeFormat format) { if (unit == null) { throw new IllegalArgumentException("Unit to register must not be null."); } if (format == null) { throw new IllegalArgumentException("Format to register must not be null."); } mCachedUnits = null; units.put(unit, format); if (unit instanceof LocaleAware) { ((LocaleAware) unit).setLocale(locale); } if (format instanceof LocaleAware) { ((LocaleAware) format).setLocale(locale); } return this; } /** * Removes the mapping for the given {@link TimeUnit} type. This effectively de-registers the unit so it will not be * used in formatting. Returns the {@link TimeFormat} that was registered for the given {@link TimeUnit} type, or * null if no unit of the given type was registered. */ public TimeFormat removeUnit(final Class unitType) { if (unitType == null) { throw new IllegalArgumentException("Unit type to remove must not be null."); } for (TimeUnit unit : units.keySet()) { if (unitType.isAssignableFrom(unit.getClass())) { mCachedUnits = null; return units.remove(unit); } } return null; } /** * Removes the mapping for the given {@link TimeUnit}. This effectively de-registers the unit so it will not be used * in formatting. Returns the {@link TimeFormat} that was registered for the given {@link TimeUnit}, or null if no * such unit was registered. */ public TimeFormat removeUnit(final TimeUnit unit) { if (unit == null) { throw new IllegalArgumentException("Unit to remove must not be null."); } mCachedUnits = null; return units.remove(unit); } @Override public String toString() { return "PrettyTime [reference=" + reference + "]"; } /** * Remove all registered {@link TimeUnit} instances. * * @return The removed {@link TimeUnit} instances. */ public List clearUnits() { List result = getUnits(); mCachedUnits = null; units.clear(); return result; } public Locale getLocale() { return locale; } /** * Set the the {@link Locale} for this {@link PrettyTime} object. This may be an expensive operation, since this * operation calls {@link TimeUnit#setLocale(Locale)} for each {@link TimeUnit} in {@link #getUnits()}. */ public PrettyTime setLocale(final Locale locale) { this.locale = locale; for (TimeUnit unit : units.keySet()) { if (unit instanceof LocaleAware) { ((LocaleAware) unit).setLocale(locale); } } for (TimeFormat format : units.values()) { if (format instanceof LocaleAware) { ((LocaleAware) format).setLocale(locale); } } return this; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy