I have a Date object that I want to convert it back to a Timestamp, the logic behind that is the user can input a event date and then that input gets converted to it's corresponding Timestamp and then uploaded to Firebase Firestore.
I have to use this method to make the sorting easier and accurate, between a list of dates, the nearest one gets displayed to user.
I have the other way around (convert a Timestamp into a date) up and running
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(timestamp * 1000L);
String date = DateFormat.format("dd-MM-yyyy hh:mm:ss", cal).toString();
How to reverse this algorithm to meet my requirements ?
According the documentation of java.util.Calendar.getTimeInMillis() it will return the current time as UTC milliseconds from epoch.
According that, you could do something as
public long dateToTimestamp(Date date) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTime(date);
return cal.getTimeInMillis() / 1000L;
}
I've tested and it works perfectly.
class Main {
public static long dateToTimestamp(Date date) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTime(date);
return cal.getTimeInMillis() / 1000L;
}
public static Date timeStampToDate(long timestamp) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(timestamp * 1000L);
return cal.getTime();
}
public static void main(String[] args) {
long date = 1000;
System.out.println("Time as Date: " + timeStampToDate(date));
System.out.println("Time in timestamp: " + dateToTimestamp(timeStampToDate(date)));
}
}
One test case that tests that the method really does the opposite than the one that you've in the question:
#Test
void testTimestampConversion() {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
// Present
long expected = dateToTimestamp(cal.getTime());
assertEquals(expected, dateToTimestamp(timeStampToDate(expected)));
// Past
long expectedPast = 1000;
assertEquals(expectedPast, dateToTimestamp(timeStampToDate(expectedPast)));
// Future
Date future = cal.getTime();
future.setYear(3000);
long expectedFuture = dateToTimestamp(future);
assertEquals(expectedFuture, dateToTimestamp(timeStampToDate(expectedFuture)));
}
Related
I'm trying to count the days between two dates but I can't get a right result.
I did the same that someone described to me.
My result should be an int or long. For this example I would expext 11 but 10 is also fine.
That's the code:
String startDate = "2018-03-25";
String endDate = "2018-04-05";
Date startDate1 = stringToDate(startDate);
Date endDate1 = stringToDate(endDate);
long ab = daysBetween(startDate1, endDate1);
String ab1 = String.valueOf(ab);
And that's the methods:
public static long daysBetween(Date startDate, Date endDate) {
Calendar sDate = getDatePart(startDate);
Calendar eDate = getDatePart(endDate);
long daysBetween = 0;
while (sDate.before(eDate)) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
public Date stringToDate(String stringDatum) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = format.parse(stringDatum);
return date;
}
catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static Calendar getDatePart(Date date){
Calendar cal = Calendar.getInstance(); // get calendar instance
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
cal.set(Calendar.MINUTE, 0); // set minute in hour
cal.set(Calendar.SECOND, 0); // set second in minute
cal.set(Calendar.MILLISECOND, 0); // set millisecond in second
return cal; // return the date part
}
java.util.Date, Calendar and SimpleDateFormat are part of a terrible API. They make the job of date/time handling harder than it already is.
Make yourself a favor and use a decent date/time library: https://github.com/JakeWharton/ThreeTenABP - here's a nice tutorial on how to use it - How to use ThreeTenABP in Android Project
With this API, it's so easy to do what you want:
LocalDate startDate = LocalDate.parse("2018-03-25");
LocalDate endDate = LocalDate.parse("2018-04-05");
long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); // 11
I've chosen to use LocalDate based on your code: the inputs have only day, month and year, and you're setting the hour/minute/seconds to zero, so I understand that you don't care about the time of the day to calculate the difference - which makes LocalDate the best choice.
Date and Calendar represent a specific point in time, and Calendar also uses a timezone, so Daylight Saving changes might affect the results, depending on the device's default timezone. Using a LocalDate avoids this problem, because this class doesn't have a timezone.
But anyway, I've tested your code and also got 11 as result, so it's not clear what problems you're facing.
private static long daysBetween(Date date1, Date date2){
return (date2.getTime() - date1.getTime()) / (60*60*24*1000);
}
import java.text.DateFormat;
import java.util.Date;
public class DatePlus {
public static void main(String[] args) {
Date now = new Date();
//Date now1 = new Date();
Date now2 = new Date();
DateFormat currentDate = DateFormat.getDateInstance();
int count1=10;
int count2=15;
Date addedDate1 = addDays(now2, count1);
Date addedDate2 = addDays(addedDate1, count2);
System.out.println(currentDate.format(addedDate1));
System.out.println(currentDate.format(addedDate2));
}
public static Date addDays(Date d, int days) {
d.setTime(d.getTime() + days * 1000 * 60 * 60 * 24);
return d;
}
}
both the date addedDate1 and addedDate2 output statements are printing the same date though the expected output is different.
The problem is that you don't return a new Date instance but change the provided one. You always modify and print the same instance.
Change your function to
public static Date addDays(Date d, int days) {
return new Date(d.getTime() + days * 1000 * 60 * 60 * 24);
}
Instead of writing your own method you can use Calender class:
public static void main(String[] args)
{
Date now = new Date();
// Date now2 = new Date();
DateFormat currentDate = DateFormat.getDateInstance();
int count1=10;
int count2=15;
Calendar c=Calendar.getInstance();
c.setTime(now);
c.add(Calendar.DATE, count1);
Date addedDate1 = c.getTime();
c.setTime(addedDate1);
c.add(Calendar.DATE, count2);
Date addedDate2 = c.getTime();
System.out.println(currentDate.format(addedDate1));
System.out.println(currentDate.format(addedDate2));
}
As mentioned already in several answers/comments, doing these calculations manually is risky and error-prone.
Here is a basic example of what you need, using Joda Time library, a very stable and well-design alternative to JDK Date, Calendar. etc...
public static void main(String[] args) {
DateTime now = new DateTime();
DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
int count1=10;
int count2=15;
DateTime addedDate1 = now.plusDays(count1);
DateTime addedDate2 = addedDate1.plusDays(count2);
System.out.println(fmt.print(addedDate1));
System.out.println(fmt.print(addedDate2));
}
Also, keep in mind that beside better design and clear documentation, Joda Time also is mostly thread-safe, as it always return immutable objects.
Finally, it's developed to be interoperable with JDK dates and calendars.
As mentionned by dystroy, you are not creating a new instance and this is the problem.
By the way, you could use an external library like Apache Commons Language to do this kind of logic, this is already well tested and you avoid such kind of problems. Commons Language has already an addDays method.
Even better, you could use Joda-Time which also has this kind of methods.
I have my MySQL database inserting timestamp when I upload a record, so what's entered is something like 2013-02-02 16:59:29. Is there a Java way to convert that into something like 10 Days Ago?
Assuming you've read the datetime value from the database into java:
Date date; // read from database
int days = TimeUnit.MILLISECONDS.toDays(
System.currentTimeMillis() - date.getTime());
then you can format it as you like.
Fetch time from mysql with the help of resultset and pass time data to below method
public static void main(String[] args) {
long timStampFromMysql = rs.getTimestamp("time");// Fetch time from mysql
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(convertTime(timStampFromMysql , 15));
System.out.println(cal);
}
public static long convertTime(long timeInMillies, int days)
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeInMillies);
calendar.add(Calendar.DAY_OF_YEAR, days);
return calendar.getTimeInMillis();
}
The Days.daysBetween from the Joda Time library will compute that for you.
DateTime start = new DateTime(time_ms);
DateTime end = new DateTime(now);
Days days = Days.daysBetween(start, end);
int d = days.getDays();
I try to subtract one day when the time inside 0:00 am - 12:00 am.
ex: 2012-12-14 06:35 am => 2012-12-13
I have done a function and It's work. But my question is any other better code in this case? Much simpler and easy to understand.
public String getBatchDate() {
SimpleDateFormat timeFormatter = new SimpleDateFormat("H");
int currentTime = Integer.parseInt(timeFormatter.format(new Date()));
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd");
String Date = dateFormatter.format(new Date());
if ( 0 <= currentTime && currentTime <= 12){
try {
Calendar shiftDay = Calendar.getInstance();
shiftDay.setTime(dateFormatter.parse(Date));
shiftDay.add(Calendar.DATE, -1);
Date = dateFormatter.format(shiftDay.getTime());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("BatchDate:", Date);
}
return Date;
}
THANKS,
Calendar shiftDay = Calendar.getInstance();
shiftDay.setTime(new Date())
if(shiftDay.get(Calendar.HOUR_OF_DAY) <= 12){
shiftDay.add(Calendar.DATE, -1);
}
//your date format
Use the Calendar class to inspect and modify the Date.
Calendar cal = new GregorianCalendar(); // initializes calendar with current time
cal.setTime(date); // initializes the calender with the specified Date
Use cal.get(Calendar.HOUR_OF_DAY) to find out the hour within the day.
Use cal.add(Calendar.DATE, -1) to set the date one day back.
Use cal.getTime() to get a new Date instance of the time that was stored in the calendar.
As with nearly all questions with regard to Date / Time, try Joda Time
public String getBatchDate() {
DateTime current = DateTime.now();
if (current.getHourOfDay() <= 12)
current = current.minusDays(1);
String date = current.toString(ISODateTimeFormat.date());
Log.d("BatchDate:" + date);
return date;
}
Say I have two date fields receiveDate and currentDate. I want to check if receiveDate was 5 days before currentDate. What I did was to convert the dates in milliseconds and then compare against 5. Is there a better way of doing so? If so, how and why mine is any less better? Thanks.
Method I wrote -
private static final double DAY_IN_MILLISECONDS = 86400000;
// Param date is the receivedDate
private long getDaysOld(final Date date) {
Calendar suppliedDate = Calendar.getInstance();
suppliedDate.setTime(date);
Calendar today = Calendar.getInstance();
today.setTime(currentDate);
double ageInMillis = (today.getTimeInMillis() - suppliedDate.getTimeInMillis());
double tempDouble;
if(isEqual(ageInMillis, 0.00) || isGreaterThan(Math.abs(ageInMillis), DAY_IN_MILLISECONDS)) {
tempDouble = ageInMillis / DAY_IN_MILLISECONDS;
} else {
tempDouble = DAY_IN_MILLISECONDS / ageInMillis;
}
long ageInDays = Math.round(tempDouble);
return ageInDays;
}
Then I have something like-
long daysOld = getDaysOld(receivedDate) ;
if(daysOld <= 5) {
.... some business code ....
}
give a try to joda-time. Time calculations with the native API is always akwards at best. Joda time makes this type of calculation MUUUCH simpler and will handle time zones pretty well also.
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Test {
private static long DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
public static void main(String[] args) throws Exception {
//
Date currentDate = getGregorianDate(1990, Calendar.JANUARY, 20);
Date receiveDate = getGregorianDate(1990, Calendar.JANUARY, 23);
//
if (getDifferenceBetweenDates(receiveDate, currentDate) < 5 * DAY_IN_MILLISECONDS) {
System.out.println("Receive date is not so old.");
}
else {
System.out.println("Receive date is very old.");
}
}
private static long getDifferenceBetweenDates(Date date1, Date date2) {
return Math.abs(date1.getTime() - date2.getTime());
}
private static Date getGregorianDate(int year, int month, int date) {
Calendar calendar = GregorianCalendar.getInstance();
calendar.set(year, month, date);
return calendar.getTime();
}
}
It can be shortened a lot:
int daysOld = (System.currentTimeMillis() - date.getTime()) / DAY_IN_MILLISECONDS;
You can't simply subtract and divide by 24*60*60*1000, because of daylight savings (in which a day could have 23 or 25 hours).
For example, in the UK the clocks moved forward by one hour on 28/03/2010. The difference between 27/03/2010 and 28/03/2010 should be 1 day, but if you follow that approach you will get 0.
You need to take the offset into account:
public static long daysBetween(Date dateEarly, Date dateLater) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(dateEarly);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(dateLater);
long endL = cal2.getTimeInMillis() + cal2.getTimeZone().getOffset( cal2.getTimeInMillis() );
long startL = cal1.getTimeInMillis() + cal1.getTimeZone().getOffset( cal1.getTimeInMillis() );
return (endL - startL) / (24 * 60 * 60 * 1000);
}
public static void main(String[] args) throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
Date foo = new Date(2010,02,27);
Date bar= new Date(2010,02,28);
System.out.println(daysBetween(foo,bar)); //prints 1
}
This all depends on what "five days" means. If you receive something monday lunchtime, then on saturday afternoon, did you receive it within five days or not? The elapsed time is greater than five days, but the day you received it is five days ago. Think about how you'd answer that question; now thing about how your mother would answer that question. It might not be the same - I would suggest that most people, particularly non-programmers, count the passing of days by the passing of local midnights. Five o'clock on wednesday morning is a day after eleven thirty on tuesday night, even though it's less than a day (less than a quarter of a day!) later.
So, i think what you want to do is compare just the dates, not the times. You can do this with Calendar by zeroing all the time fields. Given an arrivedDate and a locale (so you can tell when midnight is), i think this is correct:
Calendar deadline = Calendar.getInstance(locale);
deadline.set(Calendar.HOUR_OF_DAY, 0);
deadline.set(Calendar.MINUTE, 0);
deadline.set(Calendar.SECOND, 0);
deadline.set(Calendar.MILLISECOND, 0);
deadline.add(Calendar.DAY_OF_MONTH, 5);
Calendar arrived = Calendar.getInstance(locale);
arrived.setTime(arrivedDate);
deadline.set(Calendar.HOUR_OF_DAY, 0);
deadline.set(Calendar.MINUTE, 0);
deadline.set(Calendar.SECOND, 0);
deadline.set(Calendar.MILLISECOND, 0);
boolean arrivedWithinDeadline = arrived.compareTo(deadline) <= 0;
You should test that thoroughly before actually using it, though.
Below is my method that returns me exact difference in days,
/**
* method to get difference of days between current date and user selected date
* #param selectedDateTime: your date n time
* #param isLocalTimeStamp: defines whether the timestamp d is in local or UTC format
* #return days
*/
public static long getDateDiff(long selectedDateTime, boolean isLocalTimeStamp)
{
long timeOne = Calendar.getInstance().getTime().getTime();
long timeTwo = selectedDateTime;
if(!isLocalTimeStamp)
timeTwo += getLocalToUtcDelta();
long delta = (timeOne - timeTwo) / ONE_DAY;
if(delta == 0 || delta == 1) {
Calendar cal1 = new GregorianCalendar();
cal1.setTimeInMillis(timeOne);
Calendar cal2 = new GregorianCalendar();
cal2.setTimeInMillis(timeTwo);
long dayDiff = cal1.get(Calendar.DAY_OF_MONTH) - cal2.get(Calendar.DAY_OF_MONTH);
return dayDiff;
}
return delta;
}