Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Date to String in 'social' format

I am trying to achieve let’s say ‘social’ date format. I already have a solution, but it feels like a better one should exist. Why social and what do I mean:

If we look into Facebook time stamps of the posts we can distinguish between next options:

  1. X seconds ago
  2. X minutes ago
  3. X hours ago
  4. Yesterday at 11:07 am
  5. Friday at 9:36 pm
  6. May 5 at 5:00 pm
  7. November 20 at 9:05 pm, 2012

I made next visual timeline for better explanation: enter image description here
For example:
If the current time is: 5:33 pm, 20 sec Wednesday
The social post happened between: 00:00 am Tuesday <--> 5:33 pm, 20 sec Tuesday,
then the date format should be like: Yesterday at 11:07 am.

Solution I have:
I check each option (7 in count) and return 'social' date string.

This is how I check for option 1:

Date postDate = getPostDate();
Date nowDate = getNowDate();

// check passed seconds
int passedSeconds = getPassedSeconds(postDate, nowDate);
if (passedSeconds < 60)
{
    return passedSeconds + " seconds ago";
} 

This is how I check for option 4:

// check yesterday
Date startYesterdayDate = getZeroDayBeforeDays(nowDate, 1);
int compare = compare(startYesterdayDate, postDate);

// if postDate comes after startYesterdayDate
if (compare == -1)
{
    return "Yesterday at " + getString(postDate, "HH:mma");
}

I check other options in the same manner.


Some methods I use in my if statements above:

public static String getString(Date date, String format)
{
    Format formatter = new SimpleDateFormat(format, Locale.US);
    String s = formatter.format(date);
    return s;
}

/**
 * For example: today - 1 day
 * 
 * @param date
 * @param numOfMinusDays
 * @return
 */
public static Date getDateMinusDays(Date date, int numOfMinusDays)
{
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DAY_OF_MONTH, (0 - numOfMinusDays));
    return calendar.getTime();
}

/**
 * Get the day before today at 00:00 am.<br>
 * Means, if passed day = <b>Nov 5 13:04</b>, then returned date will be = <b>Nov 4 00:00</b> for days = 1
 * 
 * @param date
 * @param days Numner of days to reduce
 * @return
 */
public static Date getZeroDayBeforeDays(Date date, int days)
{
    Calendar yesterday = Calendar.getInstance();
    yesterday.setTime(getDateMinusDays(date, days));
    yesterday.set(Calendar.HOUR_OF_DAY, 0);
    yesterday.set(Calendar.MINUTE, 0);
    yesterday.set(Calendar.SECOND, 0);
    yesterday.set(Calendar.MILLISECOND, 1);
    return yesterday.getTime();
}


Finally, My questions:

  1. Is there a better way of converting the difference between two Dates to 'social' string format? As I said, I feel that some other way like maybe extending DateFormat object could be used, but I am not sure.

  2. How to localize the strings like 'Yesterday' and 'at', such that different Local set will change the strings to suitable language?


Sorry for such a long question, but I couldn't find shorter way to explain the need.
Thanks

like image 340
sromku Avatar asked Jun 02 '13 19:06

sromku


People also ask

How do you format a date in Java?

Java SimpleDateFormat ExampleString pattern = "MM-dd-yyyy"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); String date = simpleDateFormat. format(new Date()); System. out. println(date);


1 Answers

There is already one implemented library for that if you don't want to re invent wheel

See PrettyTime, with localization support

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”

System.out.println(p.format(new Date(1000*60*10)));
//prints: “10 minutes from now”
like image 159
jmj Avatar answered Oct 30 '22 03:10

jmj