
Convert elapsed timestamps, like, “in 3 minutes!”
PrettyTime is an OpenSource time formatting library. Completely customizable, PrettyTime creates human readable, relative timestamps like those seen on Digg, Twitter, and Facebook. It’s simple, get started “right now!” and in over 18 languages!
See also: PrettyTime Grails Plug-in, PrettyTime with JSP.
Downloads: ↓ (APL)Dependencies:Java 5.0 and up New features:Support for 18 built-in languages! |
Please open an issue if you have any suggestions, or any difficulties.
Get started now!Need help? Want to get involved?Ask a question in the forums, |
Follow @ocpsoft and @lincolnthree on Twitter.
Features:
- Generate human-readable timestamps like, “right now”, “2 days ago”, or “3 months from now”
- Simple single interface – easy to learn.
- Entirely customizable. Provide your own TimeUnit and TimeFormat objects for complete control.
- Provided integration for the JSF web-application framework
(Fork us on GitHub and send pull requests with support for other frameworks!)
Documentation:
Using PrettyTime is simple.
- Basic use in a Java App
- i18n support (contributed by Thomas Weitzel)
- Creating a custom TimeUnit
- Using PrettyTimeConverter in JSF
- Examples using JUnit
Installation
Extract necessary JAR files into your /WEB-INF/lib directory. This step is pretty straight-forward, right? Or include a maven dependency in your pom.xml (optional)
<dependency>
<groupId>org.ocpsoft.prettytime</groupId>
<artifactId>prettytime</artifactId>
<version>1.0.8.Final</version>
</dependency>
Basic use in a Java Application
PrettyTime, by default, uses the current time as the point of reference (reference time) for calculating the elapsed, or remaining time to the Date argument.
import java.util.Date;
import org.ocpsoft.pretty.time.PrettyTime;
public class BasicJavaApp
{
public static void main(String[] args)
{
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”
}
}
See below for more examples using JUnit.
i18n and multiple-languages support
PrettyTime now supports internationalization via resource bundles. Simply place an appropriate Resources_**.properties bundle on the classpath: org.ocpsoft.pretty.time.i18n, then set the desired Locale into your PrettyTime object. (contributed by Thomas Weitzel)
If you create a new Locale resource bundle for PrettyTime, please fork the project, and submit a pull request.
Locales with built-in support:
- Bulgarian – BG: Марио Георгиев
- Chinese – ZH_CN: 陈正华
- Croatian – Miroslav Rešetar
- Dutch – NL: Bram Van Dam
- English – DEFAULT
- Estonian – Matti Jagula
- French – FR: Eric Palpacuer
- German – DE: Thomas Weitzel
- Hungarian – Balázs Németh
- Italian – IT: Mirco Attocchi
- Norwegian – Magnus Byrkjeflot – www.mylog.no
- Polish – Upender Gilakathula
- Portugese – PT: Gustavo Ehrhardt
- Romanian – Upender Gilakathula
- Spanish – ES: Bruno Resano
- Slovenian- SL: Uros Majeric
- Turkish – Halil
- Vientamese – Xuân Tính – Blog
import java.util.Date;
import java.util.Locale;
import org.ocpsoft.pretty.time.PrettyTime;
public class Basic_i18n
{
public static void main(final String[] args)
{
PrettyTime p = new PrettyTime(new Locale("de"));
System.out.println(p.format(new Date()));
}
}
Creating a custom ResourceBundle
You can find full examples of resource bundles packaged inside pretty-time.jar. Also, if you create a new Locale resource bundle for PrettyTime, please fork the project, and submit a pull request.
package org.ocpsoft.pretty.time.i18n;
import java.util.ListResourceBundle;
public class Resources_de extends ListResourceBundle
{
private static final Object[][] CONTENTS = new Object[][] {
{ "CenturyPattern", "%n %u" },
{ "CenturyFuturePrefix", "In " },
{ "CenturyFutureSuffix", "" },
{ "CenturyPastPrefix", "Vor " },
{ "CenturyPastSuffix", "" },
{ "CenturyName", "Jahrhundert" },
{ "CenturyPluralName", "Jahrhunderten" }
//...
};
}
@Override
protected Object[][] getContents()
{
return CONTENTS;
}
}
Creating a custom TimeUnit:
TimeUnits are the units of measure in PrettyTime. They can be as long or as short as desired, and can be formatted into any necessary pattern. All that needs to be done is to implement the TimeUnit interface, and provide a default TimeFormat
package org.ocpsoft.pretty.time.units;
import org.ocpsoft.pretty.time.BasicTimeFormat;
import org.ocpsoft.pretty.time.TimeFormat;
import org.ocpsoft.pretty.time.TimeUnit;
public class Month implements TimeUnit
{
private static final TimeFormat defaultFormat = new BasicTimeFormat().setPattern("%n %u").setPastSuffix(" ago")
.setFutureSuffix(" from now");
private TimeFormat format = defaultFormat;
private long maxQuantity = 0;
private final long millisPerUnit = 2629743830L;
private String name = "month";
private String pluralName = "months";
/* getters and setters */
}
TimeFormat is also simple — and is the core of the Formatting platform.
package org.ocpsoft.pretty.time;
public interface TimeFormat
{
/**
* Given a populated Duration object. Apply formatting and output the
* result.
*/
public abstract String format(final Duration duration);
}
See BasicTimeFormat for an implementation example using regular expressions
JavaServer Faces support via PrettyTimeConverter
PrettyTime includes a JSF Converter for easy output formatting. No additional configuration is required to use this object, since PrettyTime includes its own META-INF/faces-config.xml — Just include the PrettyTime jar file or dependency on your classpath.
<h:outputText value="#{exampleBean.futureDate}">
<f:converter converterId="org.ocpsoft.PrettyTimeConverter"/>
</h:outputText>
In this example, futureDate must be a valid java.util.Date object.
Examples using JUnit:
See below for creating custom time units and formats:
package org.ocpsoft.pretty.time;
import static org.junit.Assert.*;
import java.text.SimpleDateFormat;
import java.util.*;
import org.junit.*;
import org.ocpsoft.pretty.time.*;
public class PrettyTimeTest
{
@Test
public void testRightNow() throws Exception
{
PrettyTime t = new PrettyTime();
assertEquals("moments from now", t.format(new Date()));
}
@Test
public void testMinutesFromNow() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
assertEquals("12 minutes from now", t.format(new Date(1000 * 60 * 12)));
}
@Test
public void testHoursFromNow() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
assertEquals("3 hours from now", t.format(new Date(1000 * 60 * 60 * 3)));
}
@Test
public void testDaysFromNow() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
assertEquals("3 days from now", t.format(new Date(1000 * 60 * 60 * 24 * 3)));
}
@Test
public void testWeeksFromNow() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
assertEquals("3 weeks from now", t.format(new Date(1000 * 60 * 60 * 24 * 7 * 3)));
}
@Test
public void testMonthsFromNow() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
assertEquals("3 months from now", t.format(new Date(2629743830L * 3L)));
}
// ... and so on
/*
* Past
*/
@Test
public void testMomentsAgo() throws Exception
{
PrettyTime t = new PrettyTime(new Date(6000));
assertEquals("moments ago", t.format(new Date(0)));
}
@Test
public void testMinutesAgo() throws Exception
{
PrettyTime t = new PrettyTime(new Date(1000 * 60 * 12));
assertEquals("12 minutes ago", t.format(new Date(0)));
}
@Test
public void testCenturiesAgo() throws Exception
{
PrettyTime t = new PrettyTime(new Date(3155692597470L * 3L));
assertEquals("3 centuries ago", t.format(new Date(0)));
}
// ...
/*
* Format duration lists
*/
@Test
public void testFormattingDurationListInThePast() throws Exception
{
PrettyTime t = new PrettyTime(new Date(1000 * 60 * 60 * 24 * 3 + 1000 * 60 * 60 * 15 + 1000 * 60 * 38));
List<Duration> durations = t.calculatePreciseDuration(new Date(0));
assertEquals("3 days 15 hours 38 minutes ago", t.format(durations));
}
@Test
public void testFormattingDurationListInTheFuture() throws Exception
{
PrettyTime t = new PrettyTime(new Date(0));
List<Duration> durations = t.calculatePreciseDuration(new Date(1000 * 60 * 60 * 24 * 3 + 1000 * 60 * 60 * 15
+ 1000 * 60 * 38));
assertEquals("3 days 15 hours 38 minutes from now", t.format(durations));
}
@Test
public void testSetLocale() throws Exception
{
PrettyTime t = new PrettyTime(new Date(315569259747L * 3L));
assertEquals("3 decades ago", t.format(new Date(0)));
t.setLocale(Locale.GERMAN);
assertEquals("vor 3 Jahrzehnten", t.format(new Date(0)));
}
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
// Stores current locale so that it can be restored
private Locale locale;
// Method setUp() is called automatically before every test method
@Before
public void setUp() throws Exception
{
locale = Locale.getDefault();
Locale.setDefault(Locale.ROOT);
}
// Method tearDown() is called automatically after every test method
@After
public void tearDown() throws Exception
{
Locale.setDefault(locale);
}
}