I try to count time interval. I parse String date into Date object for some pattern.
public static float countTimeAgo(String timestamp){
// date pattern
SimpleDateFormat simpleDateFormat
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
simpleDateFormat.setLenient(false);
// time interval
float diff;
try {
// convert timestamp to given pattern
Date timestampDate = simpleDateFormat.parse(timestamp);
// get actual date and convert to pattern
Date date = new Date();
simpleDateFormat.format(date);
// count difference in millis
diff = date.getTime() - timestampDate.getTime();
// convert millis to minutes
diff = diff/(1000*60);
} catch (ParseException e) {
return -1;
}
if (diff < 0)
return -1;
else
return diff;
}
When I put string "2018-03-08 23:28:07.807353" as argument while running my app, method is returning non -1 value. But when I run a test, it fails:
#Test
public void testCountTimeAgo(){
String date = "2018-03-08 23:28:07.807353";
assertTrue(PostTimeProvider.countTimeAgo(date) != -1);
}
AssertionError:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertTrue(Assert.java:52)
Does somebody knows why?
In your code -1 can be returned when the parsing fails or if the date was in future. You should check which one is happening in this case. Perhaps your device and the device running the unit tests have different time?
Related
I'm trying to calculate daysAgo from two dates, the phone date time and my passed date.
this is my code:
int daysAgo = DateUtilities.getTimeAgo(DateUtilities.stringToDateTime(updatedAt, true).getTime());
public static int getTimeAgo(long time) {
if (time < 1000000000000L) {
time *= 1000;
}
long now = System.currentTimeMillis();
if (time > now || time <= 0) {
return 0;
}
final long diff = now - time;
return (int) (diff / DAY_MILLIS);
}
public static Date stringToDateTime(String dateTime, boolean useUtc) throws ParseException {
if (useUtc) {
return new SimpleDateFormat("yyyy-mm-dd'T'HH:mm:ss").parse(dateTime);
} else {
return new SimpleDateFormat("yyyy-mm-dd").parse(dateTime);
}
}
this code as int daysAgo return wrong days for me, i pass this date to calculate: 2017-11-18T20:31:04.000Z and my phone date time as System.currentTimeMillis() is 1511080129979 and then result of returned daysAgo is 305
You must use "MM" to represent the month, not the "mm". It is for minutes. Your code
return new SimpleDateFormat("yyyy-mm-dd'T'HH:mm:ss").parse(dateTime);
return new SimpleDateFormat("yyyy-mm-dd").parse(dateTime);
should be changed to
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(dateTime);
return new SimpleDateFormat("yyyy-MM-dd").parse(dateTime);
The problem over here is pre-optimization.
int daysAgo = DateUtilities.getTimeAgo(DateUtilities.stringToDateTime(updatedAt, true).getTime());
return new SimpleDateFormat("yyyy-mm-dd'T'HH:mm:ss").parse(dateTime);
The above statements are perfect only when you know what they are doing, otherwise, they are impossible to even debug.
These are the situations where we understand the real importance of TDD.
The TDD approach
DateUtilitiesUnitTest
public class DateUtilitiesUnitTest
{
#Test
public void testStringToDateTimeConversion()
{
Calendar expectedCal = Calendar.getInstance();
// Here we set the month as Calendar.NOVEMBER
// As per the Calendar API, month 11 == DECEMBER
expectedCal.set(2017, Calendar.NOVEMBER, 18, 20, 31, 4);
Date actualDate = DateUtilities.stringToDateTime("2017-11-18T20:31:04.000Z");
Calendar actualCal = Calendar.getInstance();
actualCal.setTime(actualDate);
// Date.equals(Date), compares two Dates with the milliseconds precision, and cannot be used reliably
// hence, we have to compare all the individual elements separately
assertEquals("Year should be 2017", expectedCal.get(Calendar.YEAR), actualCal.get(Calendar.YEAR));
assertEquals("Month should be " + expectedCal.get(Calendar.MONTH), expectedCal.get(Calendar.MONTH), actualCal.get(Calendar.MONTH));
assertEquals("Day should be 18", expectedCal.get(Calendar.DAY_OF_MONTH), actualCal.get(Calendar.DAY_OF_MONTH));
// If required, you may go ahead and compare Hours, Minutes and Seconds
}
}
=== Step 1 (Fail the Test) ===
DateUtilities.java
public static Date stringToDateTime(String dateTime)
{
return null;
}
Test Result
java.lang.NullPointerException
=== Step 2 (Just enough to Pass the test) ===
DateUtilities.java
public static Date stringToDateTime(String dateTime)
{
Calendar cal = Calendar.getInstance();
// Here we set the month as Calendar.NOVEMBER
// As per the Calendar API, month 11 == DECEMBER
cal.set(2017, Calendar.NOVEMBER, 18, 20, 31, 4);
return cal.getTime();
}
Test Result
1 Test passed
Failing and then Passing the "pseudo tests" proves that your Test is actually working and that you are in fact testing the correct method.
=== Step 3 (Start Implementation) ===
DateUtilities.java
public static Date stringToDateTime(String dateTime)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd'T'HH:mm:ss");
Date date = null;
try {
date = format.parse(dateTime);
}
catch (ParseException e) {
e.printStackTrace();
}
return date;
}
Test Result
java.lang.AssertionError: Month should be 10
Expected :10
Actual :0
We caught the issue!
Expected month is 10 (Calendar.NOVEMBER)
but, we got 0 (Calendar.JANUARY)
=== Step 4 (Fix it!) ===
DateUtilities.java
public static Date stringToDateTime(String dateTime)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date = null;
try {
date = format.parse(dateTime);
}
catch (ParseException e) {
e.printStackTrace();
}
return date;
}
Test Result
1 Test passed
Just change the date format to
public static Date stringToDateTime(String dateTime, boolean useUtc) throws ParseException {
if (useUtc) {
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(dateTime);
} else {
return new SimpleDateFormat("yyyy-MM-dd").parse(dateTime);
}
}
In date mm denotes to minutes where MM denotes to months.
I am calculating time difference between two dates and time but its restuning invalid difference.
here's my sample date and code to calculate the difference.
loginTime=2016-01-24 12:04:30.16
expiryTime = 2016-01-24 13:04:30.16
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date now = new Date();
try {
Date startDate = simpleDateFormat.parse(loginTime);
Date expireDate = simpleDateFormat.parse(expiryTime);
// String temCurrentDate = new SimpleDateFormat("yyyy-MM-dd").format(now);
// Date currentDate = new SimpleDateFormat("yyyy-MM-dd").parse(temCurrentDate);
// String day_of_week = new SimpleDateFormat("EEEE").format(now);
long difference =startDate.getTime()- expireDate.getTime();
int hour = (int) difference / (60 * 60 * 1000);
} catch (ParseException e) {
e.printStackTrace();
}
Difference between this time is 1 hour but i am getting 11 or 13. Please tell where i am going wrong in this.
Spelling error in your variable:
simpleDateFormat.parse(expiryTime);
Does not match: ExpiryTime = 2016-01-24 13:04:30.16
That's the whole problem.
I want to Date comparison between Start Date and End Date. End Date is Greater than Start Date OR End Date is Equal to Start Date. How to possible? Its Comparison between only day. If I am enter Start Date is "15-12-2014" and End Date is "14-07-2015" then Its Not Accept. What is my Mistake? Please Guide me.
Thanks in Advance.
boolean b=false;
public boolean isDateAfter(String startDate, String endDate) {
try {
SimpleDateFormat sdf;
String myFormatString = "dd-mm-yyyy"; // for example
sdf = new SimpleDateFormat(myFormatString);
endingDate = sdf.parse(endDate);
startingDate = sdf.parse(startDate);
System.out.println("!!!!!!!!!! startingDate===="+startingDate);
System.out.println("!!!!!!!!!!! endingDate====="+endingDate);
if ((endingDate.after(startingDate))
|| (endingDate.equals(startingDate)))
b = true;
else
b = false;
} catch (Exception e) {
b = false;
}
return b;
}
Dont use SimpleDateFormat, use Time stamp like:
Long tsLong = System.currentTimeMillis() / 1000;
you can use the built in methods date.after,date.before and date.equals to do this easily
You may rely on the built-in methods like date.after() or date.before() for comparison.
For more control, you may also convert your date into long value by using date.getTime() and perform further calculations.
I have an Azure Mobile Service which returns date to an Android Client in this format
"Sat Sep 27 22:48:48 PDT 2014"
I want to calculate the difference between this returned date and today's date. After much iterations here is my current function.
public String calculateDayDifference(String DateFromAzure){
SimpleDateFormat AzureDateFormat = new SimpleDateFormat("EEE MMM dd H:m:s yyyy");
Calendar cal = Calendar.getInstance(Locale.getDefault());
String result;
try {
String currentDate = AzureDateFormat.format(System.currentTimeMillis() * 1000L);
Date presentDate = AzureDateFormat.parse(currentDate);
Date billDueDate = AzureDateFormat.parse(DateFromAzure);
long diff = billDueDate.getTime() - presentDate.getTime();
result = Long.toString(diff);
} catch (ParseException e) {
result = Long.toString(- 1);
//e.printStackTrace();
}
return result;
}
And here is how I call this function from my Adapter's getView() method
viewHolder.txtNumberDays.setText(mDateFunctions.calculateDayDifference(
viewHolder.billSummary.getBillDueDate().toString()))
And here is the Java class field that maps to the date column in the Mobile Service table.
#SerializedName("billDueDate")
private Date BillDueDate;
No matter how I tweak it, it give me negative result like so. How can I re-write the method above to return the difference between today's date and the date returned from Azure Mobile Service table?
Ok, from the AMS Android SDK source code I can see that the SDK handles formatting and parsing of dates automatically so what is returned is a valid java.util.date object.
https://github.com/Azure/azure-mobile-services/blob/master/sdk/android/src/sdk/src/com/microsoft/windowsazure/mobileservices/DateSerializer.java
With this realization I just called getTime() method on the returned date so I can compare it again current date which can be obtained from System.CurrentTimeMillis(). I then converted the result to int and that was with. Long learning experience. Its not the most efficient way to handle this but it works for. Here is the code
mBillDueDateService.mBillTable
.execute(new TableQueryCallback<Bill>() {
#Override
public void onCompleted(List<Bill> result, int count,
Exception exception, ServiceFilterResponse response) {
if (exception == null){
for (Bill bill : result){
long timeInLong = bill.getBillDueDate().getTime();
long currentTime = System.currentTimeMillis();
long diffTime = timeInLong - currentTime;
long diffDays = diffTime / (1000 * 60 * 60 * 24);
int daysdiff = (int) diffDays;
Log.i(TAG, "Bill Name " + bill.getBillName() + "" + "Due in " + daysdiff + "days");
bill.setDaysBeforeDueDate(daysdiff);
mUpcomingBillAdapter.add(bill);
}
I have converted date format in milliseconds and time format in milliseconds. I am getting current time in more than 13 digits. CurrentTime= 1357755780000, StartingTime=1357602840, EndingTime=1357756140
But when I do comparison in below code, the if part is not executed, only the else part is executed.
Is there any mistake in my code? I want to make currentTime in 10 digits. So I think, conversion of date format to milliseconds is wrong.
String toParse = getDateorTime(1) + " " + getDateorTime(2);
long currentTime=0,startingTime=0,endingTime=0,milliseconds=0;
try
{
dateFormater = new SimpleDateFormat("yyyy/MMM/dd hh:mm");
Date date = null;
try {
date = dateFormater.parse(toParse);
date.setTime(milliseconds);
}catch (Exception e) {
System.out.println("\n Error in date parsing"+e.toString());
}
currentTime = (date.getTime());
start=Long.parseLong((cursor.getString(5).trim()));
end=Long.parseLong((cursor.getString(6).trim()));
}catch (ParseException pe) {
pe.printStackTrace();
}
if((currentTime>=startingTime)&&(currentTime<=endingTime))
{
//
}
Based on your examples, you actually have startingTime and endingTime in SECONDS, while you're comparing it to currentTime in MILLISECONDS. Simply multiply the second-times by 1,000, like so:
if((currentTime>=startingTime*1000L)&&(currentTime<=endingTime*1000L))
Simply divide by 1000
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTimeInMillis()/1000);
Convert the long values to string and if length is >10 simply substring the value (0,10) and then you can use string .equals too or covert them back to long for comparison .