Best way to format a date relative to now on Android - android

I am creating a feature in an Android app to get an arbitrary date (past, present or future) and find the difference relative to now.
Both my now and due variables are longs, and this is my code:
long now = System.currentTimeMillis();
long due = now + 864000;
Log.d("Time in 1 day", DateUtils.getRelativeTimeSpanString(due,now, DateUtils.DAY_IN_MILLIS));
I want the output to be something like yesterday, today, in 4 days or 19/12/2012. However, the current output returns in 0 days...
I don't want the time to appear on these date strings.
What am I doing wrong and is the best method for formatting dates on Android?

What I have in mind is changing:
DateUtils.getRelativeTimeSpanString(due, now, 0L, DateUtils.FORMAT_ABBREV_ALL);
Since the documentation says it returns the time relative to now.
If that fails use some of the brilliant libraries:
Joda Time
PrettyTime
TimeAgo

Finally I have implemented what you wanted..!
First you need to download Joda Time from here
Extract it to any folder and put joda-time-2.2.jar into androidProject/libs folder.
MainActivity
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.MutableDateTime;
import org.joda.time.Weeks;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends Activity
{
private int day ;
private int month ;
private int year ;
private int hour ;
private int minute ;
private long selectedTimeInMillis;
private long currentTimeInMillis;
private String strDay ="";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
year = 2013;
month = 8;
day = 10;
hour = 15;
minute = 28;
DateTime selectedTime = new DateTime(year,month,day,hour,minute);
selectedTimeInMillis = selectedTime.getMillis();
MutableDateTime epoch = new MutableDateTime();
epoch.setDate(selectedTimeInMillis); //Set to Epoch time
DateTime now = new DateTime();
currentTimeInMillis = now.getMillis();
int days = Days.daysBetween(epoch, now).getDays();
int weeks = Weeks.weeksBetween(epoch, now).getWeeks();
int months = Months.monthsBetween(epoch, now).getMonths();
Log.v("days since epoch: ",""+days);
Log.v("weeks since epoch: ",""+weeks);
Log.v("months since epoch: ",""+months);
if(selectedTimeInMillis < currentTimeInMillis) //Past
{
long yesterdayTimeInMillis = currentTimeInMillis - 86400000;
DateTime today = new DateTime(currentTimeInMillis);
int year = today.getDayOfYear();
int intToday = today.getDayOfMonth();
DateTime yesterday = new DateTime(yesterdayTimeInMillis);
int intYesterday = yesterday.getDayOfMonth();
DateTime selectedDay = new DateTime(selectedTimeInMillis);
int intselectedDay = selectedDay.getDayOfMonth();
int intselectedYear = selectedDay.getDayOfYear();
if(intToday == intselectedDay & year == intselectedYear)
{
strDay = "today";
}
else if(intYesterday == intselectedDay)
{
strDay = "yesterday";
}
else
{
strDay = "before "+ days +" days from today";
}
}
else if(selectedTimeInMillis > currentTimeInMillis) //Future
{
long tomorrowTimeInMillis = currentTimeInMillis + 86400000;
DateTime tomorrow = new DateTime(tomorrowTimeInMillis);
int intTomorrow = tomorrow.getDayOfMonth();
DateTime today = new DateTime(selectedTimeInMillis);
int intToday = today.getDayOfMonth();
if(intToday == intTomorrow)
{
strDay = "tomorrow";
}
else
{
days = -days;
strDay = "after "+ days +" days from today";
}
}
Log.v("strDay: ",""+strDay);
}
}
You just need to change the value of day and you will get the desire output.
Currently I have given date 10 as input so output will be today.
I have set date/day = 10 , month = 8 , year = 2013 , hour = 15 , min = 28
For past dates:
input day 9 output yesterday
input day 3 output before 7 days from today
input year 2012 and day 10 output before 365 days from today
For future dates:
input day 11 output tomorrow
input day 27 output after 17 days from today
input day 23 and year 2016 output after 1109 days from today

Why not just check for yesterday and tomorrow to avoid the in 0 days/0 days ago bug and leave DateUtils.getRelativeTimeSpanString handle the remaining cases?
String relative = null;
if(now < due && (due-now)<864000){
relative = "tomorrow";
}else if(now > due && (now-due)<864000){
relative = "yesterday";
}else{
relative = DateUtils.getRelativeTimeSpanString(due, now, DateUtils.DAY_IN_MILLIS); // e.g. "in 4 days"
}
Log.d("result", relative);
Edit: You may also add today with a simple check as well.

Best way to format a date relative to now on Android
I suggest you to use JodaTime
It's lightweight handy library and i think actually the best tool for working with Date instances.
And you can start here.

build.gradle
compile 'joda-time:joda-time:2.9.9'
Utils.java
private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd, yyyy");
private static SimpleDateFormat TIME_FORMAT = new SimpleDateFormat(" 'at' h:mm aa");
public static String getRelativeDateTimeString(Calendar startDateCalendar) {
if (startDateCalendar == null) return null;
DateTime startDate = new DateTime(startDateCalendar.getTimeInMillis());
DateTime today = new DateTime();
int days = Days.daysBetween(today.withTimeAtStartOfDay(), startDate.withTimeAtStartOfDay()).getDays();
String date;
switch (days) {
case -1: date = "Yesterday"; break;
case 0: date = "Today"; break;
case 1: date = "Tomorrow"; break;
default: date = DATE_FORMAT.format(startDateCalendar.getTime()); break;
}
String time = TIME_FORMAT.format(startDateCalendar.getTime());
return date + time;
}
Output
Yesterday at 9:52 AM
Today at 9:52 AM
Tomorrow at 9:52 AM
Sep 05, 2017 at 9:52 AM

The actual reason is the number 864000 is in miliseconds, which corresponds to 14 minutes. 14 minutes is so small compared to DAY_IN_MILLIS (a day). There for you get "in 0 days".
If you want it to produce "in 14 mins", just change DAY_IN_MILLIS to MIN_IN_MILLIS.

I came here for an alternative but I can't find perfect rather than my code.
So I shared here any improvements are welcome.
public String getCreatedAtRelative() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
df.setTimeZone(TimeZone.getTimeZone("IST"));
CharSequence relative = null;
try {
relative = DateUtils.getRelativeTimeSpanString(df.parse(createdAt).getTime(), new Date().getTime(),
0L, DateUtils.FORMAT_ABBREV_ALL);
} catch (ParseException e) {
Log.e("Parse Exception adapter", "created at", e);
} catch (NullPointerException e) {
e.printStackTrace();
}
if (null == relative) {
return createdAt;
} else {
return relative.toString().replace(".", " ");
}
}

So your computation is based on milliseconds unit, then you format the result with SimpleDateFormat.
For this, you can easily use SimpleDateFormat formatter like this :
Date date = new Date(milliseconds);
SimpleDateFormat formatter = new SimpleDateFormat("EEEE dd MMMM yyyy");
String strDate = formatter.format(date);
So your computation should be based on milliseconds unit, then you format the result with SimpleDateFormat.
The pattern ("EEEE dd MMMM yyyy") allows you to get a date format like Monday, 04 February 2013.
You can change the pattern as you like : "EEEE dd/MM/yy", ...

for Android you can use most simple way with Joda-Time-Android library:
Date yourTime = new Date();
DateTime dateTime = new DateTime(yourTime); //or simple DateTime.now()
final String result = DateUtils.getRelativeTimeSpanString(getContext(), dateTime);

long now = System.currentTimeMillis();
DateUtils.getRelativeDateTimeString(mContext, now), DateUtils.SECOND_IN_MILLIS, DateUtils.DAY_IN_MILLIS, 0)
a link!

Related

String Date to Milliseconds Android [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Calculate date/time difference in java
how would a future date such as Sat Feb 17 2012 be converted into milliseconds in java that can then be subtracted from the current time in milliseconds to yield time remaining until that future date.
The simplest technique would be to use DateFormat:
String input = "Sat Feb 17 2012";
Date date = new SimpleDateFormat("EEE MMM dd yyyy", Locale.ENGLISH).parse(input);
long milliseconds = date.getTime();
long millisecondsFromNow = milliseconds - (new Date()).getTime();
Toast.makeText(this, "Milliseconds to future date="+millisecondsFromNow, Toast.LENGTH_SHORT).show();
A more difficult technique (that basically does what DateFormat does for you) involves parsing it yourself (this would not be considered best practice):
String input = "Sat Feb 17 2012";
String[] myDate = input.split("\\s+");
int year = Integer.parseInt(myDate[3]);
String monthString = myDate[1];
int mo = monthString.equals("Jan")? Calendar.JANUARY :
monthString.equals("Feb")? Calendar.FEBRUARY :
monthString.equals("Mar")? Calendar.MARCH :
monthString.equals("Apr")? Calendar.APRIL :
monthString.equals("May")? Calendar.MAY :
monthString.equals("Jun")? Calendar.JUNE :
monthString.equals("Jul")? Calendar.JULY :
monthString.equals("Aug")? Calendar.AUGUST :
monthString.equals("Sep")? Calendar.SEPTEMBER :
monthString.equals("Oct")? Calendar.OCTOBER :
monthString.equals("Nov")? Calendar.NOVEMBER :
monthString.equals("Dec")? Calendar.DECEMBER : 0;
int day = Integer.parseInt(myDate[2]);
Calendar c = Calendar.getInstance();
c.set(year, mo, day);
long then = c.getTimeInMillis();
Time current_time = new Time();
current_time.setToNow();
long now = current_time.toMillis(false);
long future = then - now;
Date d = new Date(future);
//TODO use d as you need.
Toast.makeText(this, "Milliseconds to future date="+future, Toast.LENGTH_SHORT).show();
Firts, you must parse you String to get its Date representation. Here are examples and some docs.
Then you shoud call getTime() method of your Date.
DateFormat format = new SimpleDateFormat("EEE MMM dd yyyy", Locale.US);
long futureTime = 0;
try {
Date date = format.parse("Sat Feb 17 2012");
futureTime = date.getTime();
} catch (ParseException e) {
Log.e("log", e.getMessage(), e);
}
long curTime = System.currentTimeMillis();
long diff = futureTime - curTime;
Pass year, month and day of the future date in the date of this code and variable diff will give the millisecond time till that date,
Date date = new GregorianCalendar(year, month, day).getTime();
Date today = new Date();
long diff = date.getTime() - today.getTime();
You can simply call the getTime() method of date object. please follow through the sample below
import java.util.Date;
public class Test {
#SuppressWarnings("deprecation")
public static void main(String[] args) {
System.out.println(new Date("Sat Feb 17 2012").getTime());
}
}
try { String str_date="11-June-07";
SimpleDateFormat formatter ;
Date date ;
formatter = new SimpleDateFormat("dd-MMM-yy");
date = (Date) formatter.parse(str_date);
Log.i("test",""+date);
} catch (Exception e)
{System.out.println("Exception :"+e); }
Date d = new Date();
long time = d.getTime();
long timeDiff = time - lastTime;
//timeDiff will contain your value.
//import these two,
//import java.text.SimpleDateFormat;
//import java.util.Date;

Joda - Get the age from a birthday using a different format

I'm learning how to build Android applications, and I'm trying to get the age from my users, only using the birthday.
I'm already using Joda timer, but I'm getting the data from a Json file, and this Json file outputs the data like this:
1994-11-24 / YYYY-MM-d
I'm getting the json data inside a for loop, in Java.
//Variable
private static final String TAG_BIRTH_DATE = "birth_date";
...
//inside the Loop
String birth_date = c.getString(TAG_BIRTH_DATE);
My question is, how can I format the date, and get the age from the person?
I tried this, so far.
DateTimeFormatter formatter = DateTimeFormat.forPattern("d/MM/yyyy");
LocalDate date = formatter.parseLocalDate(birth_date);
LocalDate birthdate = new LocalDate (date);
LocalDate now = new LocalDate();
Years age = Years.yearsBetween(birthdate, now);
But is not working.
Thank you.
Try below method to calculate age of user and in parameter pass your date that you are getting from JSON
public static int getAge(String dateOfBirth) {
Calendar today = Calendar.getInstance();
Calendar birthDate = Calendar.getInstance();
int age = 0;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
Date convertedDate = new Date();
try {
convertedDate = dateFormat.parse(dateOfBirth);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
birthDate.setTime(convertedDate);
if (birthDate.after(today)) {
throw new IllegalArgumentException("Can't be born in the future");
}
age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);
// If birth date is greater than todays date (after 2 days adjustment of
// leap year) then decrement age one year
if ((birthDate.get(Calendar.DAY_OF_YEAR)
- today.get(Calendar.DAY_OF_YEAR) > 3)
|| (birthDate.get(Calendar.MONTH) > today.get(Calendar.MONTH))) {
age--;
// If birth date and todays date are of same month and birth day of
// month is greater than todays day of month then decrement age
} else if ((birthDate.get(Calendar.MONTH) == today.get(Calendar.MONTH))
&& (birthDate.get(Calendar.DAY_OF_MONTH) > today
.get(Calendar.DAY_OF_MONTH))) {
age--;
}
return age;
}
You have just mismatched your pattern and then accepted an answer which uses minutes instead of months (small "m" versus big "M). The Joda-answer would be (pay attention to the different pattern please):
String birth_date = c.getString(TAG_BIRTH_DATE); // example: 1994-11-24
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-d");
LocalDate date = formatter.parseLocalDate(birth_date);
Years age = Years.yearsBetween(date, LocalDate.now());

Cant fetch current time, date showing year as 1970

public static final String inputFormat = "HH:mm";
private Date date;
private Date dateCompareOne;
private Date dateCompareTwo;
LINE 5:
private String compareStringOne = String.valueOf(SetTimeActivity.intFromTimeH)+ ":"+ String.valueOf(SetTimeActivity.intFromTimeM) ;
LINE 6:
private String compareStringTwo = String.valueOf(SetTimeActivity.intToTimeH) + ":"+ String.valueOf(SetTimeActivity.intToTimeM);
SimpleDateFormat inputParser = new SimpleDateFormat(inputFormat, Locale.US);
private void compareDates()
{
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
date = parseDate(hour + ":" + minute);
dateCompareOne = parseDate(compareStringOne);
dateCompareTwo = parseDate(compareStringTwo);
if (!(dateCompareOne.before( date ) && dateCompareTwo.after(date))) {
....
I am trying to check if current time falls between the specified time. For that I am converting the specified time into strings first (in Line5 & Line6). Even though I get the integer values correct, the string formed always shows "0:0".
Also, the year is shown as 1970 (The date & the day shown are wrong as well).
I need to get the current time. What am I doing wrong?
private Date parseDate(String date) {
try {
return inputParser.parse(date);
} catch (java.text.ParseException e) {
return new Date(0);
}
}
The parseDate() function returns the time elapsed since the 1st of January 1970. This is known as the Unix Epoch, and it's how all time is represented in Unix computers. By running the parseDate function on a string containing just hours and minutes, you're creating a Date object which represents a time HH:mm past the first of January 1970.
Your code is using a really odd way of getting the current time. Converting a Calendar to two ints, then to a string and finally parsing back to a Date is going to be inefficient and open you up to all sorts of needless errors.
When you initialise a new Date object it is automatically assigned the time of initialisation. Therefore:
Date d = new Date();
would result in d being the moment of initialisation (that is, this year, month, day, hour, minute, second and microsecond). Then you can just use Date.after() and Date.before().
If you still want to do it via the Calendar method, then you'd be better served by:
cal = Calendar.getInstance();
Date d = cal.getTime();
It may be that you've got other issues, but it's worth doing it properly first. When you pass data by writing it as a string (especially when it's time related, with all sorts of ambiguities about what "12" actually represents) you lose all the advantages that language typing gives you.
this code help you
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE); if (c.get(Calendar.AM_PM) == Calendar.AM)
am_pm = "AM";
else if (c.get(Calendar.AM_PM) == Calendar.PM)
am_pm = "PM";
// Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
String formattedDate = df.format(c.getTime());
Toast.makeText(this, formattedDate, Toast.LENGTH_SHORT).show();
If you already work with Date objects why not using the Date.after(...) and Date.before(...) methods.

Convert Date to Year and Month

I am writing an application in which I have to display a date . Now I want to convert that date into Year and Month from the Current Date.
My Date is Like - 29/03/2017.
I want to convert this date into Year and Months.
Sorry I think you are not able to understand my question. I want the Difference of current date and above date in year and months.
Sorry for my explanation.
You can use Joda Time and compute a Period between two LocalDate values (which is what you've got here) using months and years as the units.
example
LocalDate dob = new LocalDate(1992, 12, 30);
LocalDate date = new LocalDate(2010, 12, 29);
Period period = new Period(dob, date, PeriodType.yearMonthDay());
System.out.println(period.getYears() + " years and " +
period.getMonths() + " months");
I found my answer using Calender class .
First i find the difference between two days and using that days i found the years and months.
Here i post my code, which i think help to others.
int days = Integer.parseInt(Utility.getDateDiffString("29/03/2017"));
int years = days/365;
int remainingDays = days - (365*years);
int months = remainingDays/30;
getDateDiffString() Method. In this method we need to pass end date
public static String getDateDiffString(String endDate)
{
try
{
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date dateTwo = dateFormat.parse(endDate);
long timeOne = cal.getTimeInMillis();
long timeTwo = dateTwo.getTime();
long oneDay = 1000 * 60 * 60 * 24;
long delta = (timeTwo - timeOne) / oneDay;
if (delta > 0) {
return "" + delta + "";
}
else {
delta *= -1;
return "" + delta + "";
}
}
catch (Exception e)
{
e.printStackTrace();
}
return "";
}
if your date's format is fixed, you can do it like this :
String myDate = "29/03/2017";
String newDate = myDate.subString(6, 10) + "-" + myDate.subString(3, 5)
this method to convert the normal string to date format
String currentDateString = "02/27/2012 17:00:00";
SimpleDateFormat sd = new SimpleDateFormat("mm/dd/yyyy HH:mm:ss");
Date currentDate = sd.parse(currentDateString);
after that you get the formal method
You Should use SimpleDateFormate !
For Example:--- You can get time & Date as you want:-
Date email_date = m.getSentDate();// this is date which you are getting
DateFormat date = new SimpleDateFormat("EEE MMM yyyy");
DateFormat time = new SimpleDateFormat("hh:mm aa");
String date_str=date.format(email_date);
String time_str=time.format(email_date);
Use Java Calendar class to get year from date
Calendar c=Calendar.getInstance();
SimpleDateFormat simpleDateformat=new SimpleDateFormat("yyyy MMM");
System.out.println(simpleDateformat.format(c.getTime()));
To get difference between two date
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) )
long timeDiff = (d1.getTime() - d2.getTime());
String diff=String.format("%d year(s) %d day(s) %d hour(s) %d min(s) %d sec(s)",(TimeUnit.MILLISECONDS.toDays(timeDiff)/365),TimeUnit.MILLISECONDS.toDays(timeDiff)%365,
TimeUnit.MILLISECONDS.toHours(timeDiff)
- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS
.toDays(timeDiff)),
TimeUnit.MILLISECONDS.toMinutes(timeDiff)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS
.toHours(timeDiff)),
TimeUnit.MILLISECONDS.toSeconds(timeDiff)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
.toMinutes(timeDiff)));
System.out.println(diff);
Specify correct date here in d1 & d2.Then you will get right answer of difference
First put your Date into a String variable as:
String dateToConvert = "29/03/2017";
Instantiate Calendar as:
Calendar convertedDate = Calendar.getInstance();
Set that date to calendar
convertedDate.set(dateToConvert);<br/>
Then use this line:
String datePicked = DateFormat.getDateInstance().format(convertedDate.getTime());
Output: Mar 29, 2017

Android How to change Total number of days into years,months and days exactly?

i am doing an app that is related to get the age of a person according to the given input of birthday date. for that i am getting the total number of days from that date to the current date from the below code.
String strThatDay = "1991/05/10";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
Date d = null;
try {
try {
d = formatter.parse(strThatDay);
Log.i(TAG, "" +d);
} catch (java.text.ParseException e) {
e.printStackTrace();
}
} catch (ParseException e) {
e.printStackTrace();
}
Calendar thatDay = Calendar.getInstance();
thatDay.setTime(d); //rest is the same....
Calendar today = Calendar.getInstance();
long diff = today.getTimeInMillis() - thatDay.getTimeInMillis();
long days = diff / (24 * 60 * 60 * 1000);
from this code i am getting total number of days. so my requirement is convert the total number of days in to years ,months and days exactly.. please help....
You should use the Duration class :
Duration duration = new Duration();
duration.add( today );
duration.substract( birthDate);
int years = duration.getYears();
int months = duration.getMonths();
int days = duration.getDays();
Some other alternatives include using a library dedicated to time management : Joda time. See Calculate age in Years, Months, Days, Hours, Minutes, and Seconds
String strThatDay = "1991/05/10";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
Date thatDate = null;
try {
try {
thatDate = formatter.parse(strThatDay);
Calendar thatDay = Calendar.getInstance();
thatDay.setTime(thatDate);
Calendar toDay = Calendar.getInstance();
toDay.setTime(thatDate);
toDay.add(Calendar.DATE, noOfDays);
int year = toDay.getTime().getYear() - thatDay.getTime().getYear();
int month = toDay.getTime().getMonth() - thatDay.getTime().getMonth();
if(month<0){
year--
month = month+12;
}
int days = toDay.getTime().getDate() - thatDay.getTime().getDate();
if(month<0){
month--
days = days+ toDay.getMaximum(Calendar.MONTH);;
}

Categories

Resources