In this part of my code I want Joda Time to calculate and show how much time left until next birthday. So the year should change on birthday
DateTime startDate = DateTime.now();
DateTime endDate = new DateTime(x,m110,d110,h120,min120);
Period period = new Period(startDate, endDate, PeriodType.dayTime());
textView3.setText(formatter.print(period));
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendMonths().appendSuffix(".")
.appendDays().appendSuffix(" ")
.appendHours().appendSuffix(":")
.appendMinutes().appendSuffix(":")
.appendSeconds()
.toFormatter();
x here is year, m110, d110, h120, min120 - month, day, hour and minute. What should I write instead of "x", so it could count how much time left every year and not once. And another question. When it's, for example, 3 hours, 4 minutes, what should I do in order to display "03:04:00" instead of "3:4:" (it also just doesn't show 0)
The value of x is dependent of whether the birthday has already happend this year or not. You can check this using DateTime.before methods on the same day and month in the current year:
DateTime startDate = DateTime.now();
int year = startDate.getYear();
DateTime endDate = new DateTime(year,m110,d110,h120,min120);
if (endDate.isBefore(startDate)) // birthday happend already this year?
endDate = endDate.plusYears(1); // then the next one is in the next year
As for your second question:
You can advice the builder to create a formatter which always prints zeros using printZeroAlways(). To get the formatter to print at least two digits you can use the minimumPrintedDigits method:
PeriodFormatter formatter = new PeriodFormatterBuilder()
.minimumPrintedDigits(0)
.appendMonths().appendSuffix(".")
.printZeroAlways()
.appendDays().appendSuffix(" ")
.minimumPrintedDigits(2)
.appendHours().appendSuffix(":")
.appendMinutes().appendSuffix(":")
.appendSeconds()
.toFormatter();
Note that those methods only apply to the fields added after the invocation of the method. Also, the value may change along the builder's creation several times.
Related
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calender = Calendar.getInstance();
calender.set(Calendar.DAY_OF_MONTH, calender.getActualMaximum(Calendar.DATE));
int months = 1;
calender.add(Calendar.MONTH, months );
String time = sdf .format(calender .getTime());
System.out.println(time);
Since current month is April and last date is 2020-04-30
Next month last date I should get 2020-05-31
but I am getting last date as 2020-05-30
Any thing am i doing wrong ?
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It’s much nicer to work with than the old classes Calendar and SimpleDateFormat.
LocalDate endOfNextMonth =
YearMonth // Represent an entire month in a particular year.
.now(ZoneId.of("Europe/Volgograd")) // Capture the current year-month as seen in a particular time zone. Returns a `YearMonth` object.
.plusMonths(1) // Move to the next month. Returns another `YearMonth` object.
.atEndOfMonth(); // Determine the last day of that year-month. Returns a `LocalDate` object.
String time = endOfNextMonth.toString(); // Represent the content of the `LocalDate` object by generating text in standard ISO 8601 format.
System.out.println("Last day of next month: " + time);
Output when running today:
Last day of next month: 2020-05-31
A YearMonth, as the name maybe says, is a year and month without day of month. It has an atEndOfMonth method that conveniently gives us the last day of the month as a LocalDate. A LocalDate is a date without time of day, so what we need here. And its toString method conveniently gives the format that you wanted (it’s ISO 8601).
Depending on the reason why you want the last day of another month there are a couple of other approaches you may consider. If you need to handle date ranges that always start and end on month boundaries, you may either:
Represent your range as a range of YearMonth objects. Would this free you from knowing the last day of the month altogether?
Represent the end of your range as the first of the following month exclusive. Doing math on the 1st of each month is simpler since it is always day 1 regardless of the length of the month.
What went wrong in your code?
No matter if using Calendar, LocalDate or some other class you need to do things in the opposite order: first add one month, then find the end of the month. As you know, months have different lengths, so the important part is getting the end of that month where you want to get the last day. Putting it the other way: setting either a LocalDate or a Calendar to the last day of the month correctly sets it to the last day of the month in qustion but does not instruct it to stay at the last day of the month after subsequent changes to its value, such as adding a month. If you add a month to April 29, you get May 29. If you add a month to April 30, you get May 30. Here it doesn’t matter that 30 is the last day of April while 30 is not the last day of May.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
You'd better use LocalDate like this:
LocalDate now = LocalDate.now();
LocalDate lastDay = now.withDayOfMonth(now.lengthOfMonth());
LocalDate nextMonth = lastDay.plusMonths(1);
Don't use deprecated classes from java.util.*.
Use classes from java.time.*.
Example with LocalDate :
public class Testing {
public static void main(String args[]) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.now();
int months = 1;
date = date.plusMonths(months);
date = date.withDayOfMonth(date.lengthOfMonth());
System.out.println(date.format(dateTimeFormatter));
}
}
Output :
2020-05-31
Example with Calendar :
public class Testing {
public static void main(String args[]) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calender = Calendar.getInstance();
int months = 1;
calender.add(Calendar.MONTH, months);
calender.set(Calendar.DAY_OF_MONTH, calender.getActualMaximum(Calendar.DAY_OF_MONTH));
String time = sdf.format(calender.getTime());
System.out.println(time);
}
}
Output :
2020-05-31
Lets say I have to subtract Arrival time by departing time of specific days. How would I do this in Java using Gregorian calendar?
public Duration getDuration(){
SimpleDateFormat date = new SimpleDateFormat("YYYYMMDD");
SimpleDateFormat time = new SimpleDateFormat("HHMM");
String ArivalTime = "1720"
String DepartingTime = "1100"
String ArivalDate = "20200220"
String DepartingDate = "20200211"
Calendar departureDateCalc = new GregorianCalendar();
//return duration;
}
the code is barely anything. But I need to subtract an Arrival date by Departing date
java.time
Don’t use GregorianCalendar for this. Use java.time, the modern Java date and time API.
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmm");
String arrivalTime = "1720";
String departingTime = "1100";
String arrivalDate = "20200220";
String departingDate = "20200211";
String arrivalTimeZone = "Africa/Niamey";
String departingTimeZone = "America/Mendoza";
ZonedDateTime departure = LocalDate.parse(departingDate, DateTimeFormatter.BASIC_ISO_DATE)
.atTime(LocalTime.parse(departingTime, timeFormatter))
.atZone(ZoneId.of(departingTimeZone));
ZonedDateTime arrival = LocalDate.parse(arrivalDate, DateTimeFormatter.BASIC_ISO_DATE)
.atTime(LocalTime.parse(arrivalTime, timeFormatter))
.atZone(ZoneId.of(arrivalTimeZone));
Duration difference = Duration.between(departure, arrival);
System.out.println(difference);
This outputs:
PT218H20M
So a period of time of 218 hours 20 minutes. If you want it more readable:
String diffString = String.format(
"%d days %d hours %d minutes", difference.toDays(),
difference.toHoursPart(), difference.toMinutesPart());
System.out.println(diffString);
9 days 2 hours 20 minutes
The conversion to days assumes that a day is always 24 hours, which may not be the case in either of the departure or the arrival time zone, for example when they go from standard to summer time (DST) or vice versa.
Don’t use GregorianCalendar
The GregorianCalendar class is poorly designed and long outdated. Don’t use it. For anything. If you had wanted to use it for finding a duration, the way would have been to add one day at a time to the departure time until you reach the arrival time. If you’re past it, subtract one day again and start counting hours, again by adding one at a time. Same with minutes. It’s way more complicated and also more error-prone than using the Duration class directly.
Link
Oracle tutorial: Date Time explaining how to use java.time.
I am trying to obtaining remaining years, months, and days between two dates:
So I have used Joda Time to do so:
DateTime endDate = new DateTime(2018,12,25,0,0);
DateTime startDate = new DateTime();
Period period = new Period(startDate,endDate,PeriodType.yearMonthDay());
PeriodFormatter formatter = new PeriodFormatterBuilder().appendYears().appendSuffix(" Year ").
appendMonths().appendSuffix(" Month ").appendDays().appendSuffix(" Day ").appendHours()..toFormatter();
String time = formatter.print(period);
This gives me string time: 2 Year 4 Month 22 Day
However, I want integer values of each number of remaining years, months, days.
So, Instead of "2 Year 4 Month 22 Day", I want to set my variables:
int year = 2
int month = 4
int day = 22
Is there any way to obtain these values separately instead of obtaining one string? Thank you so much! :)
i had the same requirement once ,here is the code snippet
LocalDate d=LocalDate.of(yy,mm,dd);
LocalDate d2=LocalDate.of(yy, mm, dd);
Period p=Period.between(d, d2);
long day,month,year;
day=p.getDays();
month=p.getMonths();
year=p.getYears();
System.out.println(day+" : "+month+" : "+year);
Invoke the methods provided by the DateTime class and just subtract them. An example for years is below:
int year = (int) dateTime#year#getField() - (int) dateTime2#year#getField()
UNTESTED code!! I'll be looking into it later but the general idea is the same, get the field information then just subtract it to get a value
Am trying to get a LocalDate instance for each Year in a Period. For example, for this:
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(2011, Month.DECEMBER, 19);
Period period = Period.between(birthday, today);
I want 2012-12-19, 2013-12-19, 2014-12-19, 2015-12-19.
Given the methods of Period this isn't possible. Is there a way around this? Is it possible using another method?
Care must be taken when looping over dates. The "obvious" solution does not work properly. The solution of Soorapadman will work fine for the date given (the 19th December), but fail if the start date is the 29th February. This is because 1 year later is the 28th, and the date will never return to the 29th February, even when another leap year occurs.
Note that this problem is more pronounced for month addition. A start date of the 31st January will return the sequence 28th February (or 29th), then 28th March 28th April and so on. This is unlikely to be the desired output, which is probably the last date of each month.
The correct strategy is as follows:
public List<LocalDate> datesBetween(LocalDate start, LocalDate end, Period period);
List<LocalDate> list = new ArrayList<>();
int multiplier = 1;
LocalDate current = start;
while (!current.isAfter(end)) {
current = start.plus(period.multipliedBy(multiplier);
list.add(current);
multiplier++;
}
return list;
}
Note how the strategy adds an increasing period to the same start date. The start date is never altered. Using the same start date is critical to retain the correct month length of that date.
You can try like this using Java 8;
LocalDate start = LocalDate.of(2011, Month.DECEMBER, 19);
LocalDate end = LocalDate.now();
while (!start.isAfter(end)) {
System.out.println(start);
start = start.plusYears(1);
}
}
The date is selected by the user using a drop down for year, month and day. I have to compare the user entered date with today's date. Basically see if they are the same date. For example
the user entered 02/16/2012. And if today is 02/16/2012 then I have to display a message. How do I do it?
I tried using milliseconds but that gives out wrong results.
And what kind of object are you getting back? String, Calendar, Date? You can get that string and compare it, at least that you think you'll have problems with order YYYY MM DD /// DD MM YYY in that case I suggest to create a custom string based on your spec YYYYMMDD and then compare them.
Date d1 = new Date();
Date d2 = new Date();
String day1 = d1.getYear()+"/"+d1.getMonth()+"/"+d1.getDate();
String day2 = d2.getYear()+"/"+d2.getMonth()+"/"+d2.getDate();
if(day1.equals(day2)){
System.out.println("Same day");
}
Dates in java are moments in time, with a resolution of "to the millisecond". To compare two dates effectively, you need to first set both dates to the "same time" in hours, minutes, seconds, and milliseconds. All of the "setTime" methods in a java.util.Date are depricated, because they don't function correctly for the internationalization and localization concerns.
To "fix" this, a new class was introduced GregorianCalendar
GregorianCalendar cal1 = new GregorianCalendar(2012, 11, 17);
GregorianCalendar cal2 = new GregorianCalendar(2012, 11, 17);
return cal1.equals(cal2); // will return true
The reason that GregorianCalendar works is related to the hours, minutes, seconds, and milliseconds being initialized to zero in the year, month, day constructor. You can attempt to approximate such with java.util.Date by using deprecated methods like setHours(0); however, eventually this will fail due to a lack of setMillis(0). This means that to use the Date format, you need to grab the milliseconds and perform some integer math to set the milliseconds to zero.
date1.setHours(0);
date1.setMinutes(0);
date1.setSeconds(0);
date1.setTime((date1.getTime() / 1000L) * 1000L);
date2.setHours(0);
date2.setMinutes(0);
date2.setSeconds(0);
date2.setTime((date2.getTime() / 1000L) * 1000L);
return date1.equals(date2); // now should do a calendar date only match
Trust me, just use the Calendar / GregorianCalendar class, it's the way forward (until Java adopts something more sophisticated, like joda time.
There is two way you can do it. first one is format both the date in same date format or handle date in string format.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String date1 = sdf.format(selectedDate);
String date2 = sdf.format(compareDate);
if(date1.equals(date2)){
}else{
}
Or
Calendar toDate = Calendar.getInstance();
Calendar nowDate = Calendar.getInstance();
toDate.set(<set-year>,<set-month>,<set-date->);
if(!toDate.before(nowDate))
//display your report
else
// don't display the report
Above answers are correct but consider using JodaTime - its much simpler and intuitive API.
You could set DateTime using with* methods and compare them.
Look at this answer