I try to parse date string but always get wrong month. Here's my code.
This is code to select date from calender
#OnClick(R.id.tedit_tgllahir_addnew) void showTimeDialog(){
calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH);
date = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(AddDataForNewUserActivity.this,
new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
etTgl.setText(String.format("%02d/%02d/%02d", year, month+1, dayOfMonth));
}
}, year, month, date);
datePickerDialog.show();
}
and this is when i want to parse data
birth = LocalDate.of(list.getTglLahirAnak().getYear() + 1900, list.getTglLahirAnak().getMonth(), list.getTglLahirAnak().getDate());
int year = Period.between(birth, LocalDate.now()).getYears();
int month = Period.between(birth, LocalDate.now()).getMonths();
int totalBulan = year * 12 + month;
Whenever I input date from the calender, it always shows the wrong month. For example I choose May but in the system read April. Thanks to all who are willing to help.
I gather from your question that you are using the backport of JSR-310, probably the Android edition, ThreeTenABP. If so, go all-in on that and drop the use of the poorly designed and long outdated Calendar and Date classes.
Even if the use of the Date class is dictated from outside of your control, you must still stay away from its deprecated methods including getYear(), getMonth() and getDate(). You are trying the good thing when receiving a Date and converting it to a LocalDate first thing. Use DateTimeUtils from the backport for a first conversion.
But let’s take it from the top. Use LocalDate for setting the initial date of your date picker. Don’t use the old-fashioned Calendar class. I have not compiled the code, so please forgive if there’s a typo.
LocalDate today = LocalDate.now(ZoneId.systemDefault());
year = today.getYear();
month = today.getMonthValue(); // naturally 1-based
date = today.getDayOfMonth();
DatePickerDialog datePickerDialog = new DatePickerDialog(AddDataForNewUserActivity.this,
new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
// will return to this part later
}
}, year, month - 1, date); // Pass 0-based month
When the user selects a date from the calendar/date picker, don’t store it as a string. Store it as a LocalDate object. This saves you from doing any parsing later, and your code also shows that you need a LocalDate. Obviously if you want to show the selected date to the user, format the date into a string for that purpose (only). Use a DateTimeFormatter for formatting:
private static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("yy/MM/dd");
Now we go:
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
// Store the selected date somewhere you can find it later
selectedLocalDate = LocalDate.of(year, month + 1, dayOfMonth);
// Display to the user
String formattedDate = selectedLocalDate.format(dateFormatter);
etTgl.setText(formattedDate);
}
Now the calculation of age in months poses no problem anymore:
birth = selectedLocalDate;
long totalBulan = Period.between(birth, LocalDate.now(ZoneId.systemDefault()))
.toTotalMonths();
If you cannot control what you get from list.getTglLahirAnak(), the conversion from Date to LocalDate is:
Date oldfashionedDate = list.getTglLahirAnak();
birth = DateTimeUtils.toInstant(oldfashionedDate)
.atZone(ZoneId.systemDefault())
.toLocalDate();
Now the calculation of age proceeds as before.
What went wrong in your code?
Just like the outdated Calendar also the deprecated Date.getMonth() numbers the months from 0 for January through 11 for December. So if you pick a date in May, list.getTglLahirAnak().getMonth() returns 4 for May. When you feed this into a LocalDate with its natural and sensible month numbering, it gives you April.
Related
1.Now I was trying to create a SimpleDateFormat that only contain weekday name, hour and minutes.
I just defined a schema like this: DateFormat sdf = new SimpleDateFormat("EEE:hh:mm"); However, it seems like this pattern did not work at all;
2.Here is my code to define a date format, the code below can only contain hours and minutes, When I try to input "Tue:21:30", "Tue" will not be stored. How can defined a time format just like ""Tue 21:30""?
DateFormat sdf = new SimpleDateFormat("EEE:hh:mm");
Date date = sdf.parse("Tue:21:30");
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int hours = 8;
int minutes =3000;
cal.add(Calendar.HOUR_OF_DAY, hours);
cal.add(Calendar.MINUTE, minutes);
date = cal.getTime();
System.out.println(date);
System.out.println(date.getDay());
System.out.println(date.getHours())
The java.util.Date class represents the combination of a date with with a time-of-day as seen in UTC.
You have only a day-of-week, not a date. And you have no indicator of offset or time zone. You have only one of the pieces needed, a time-of-day. So it makes no sense to parse a string such as "Tue:21:30".
Another thing: You are using terrible date-time classes. These classes were supplanted years ago by the modern java.time classes defined in JSR 310.
To pair a day-of-week with a time-of-day, write a class. In Java 16, I would use the new records feature to briefly write such a class. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
record DayOfWeekTime ( DayOfWeek dayOfWeek , LocalTime localTime ) {}
Usage.
DayOfWeekTime dowTime = new DayOfWeekTime( DayOfWeek.TUESDAY , LocalTime.of( 21 , 30 ) ) ;
Or use a pair of int values for hour and minute instead of LocalTime if you want to restrict the data that way. I would add an explicit constructor too, to validate the range of allowed values on those int inputs.
record DayOfWeekTime ( DayOfWeek dayOfWeek , int hour , int minute ) {}
Add methods to parse and generate strings in your desired format.
You might want to add a compareTo method to implement the Comparable interface, if you need sorting.
Date represents an instant in time. "9:30 pm on Tuesday" is not an instant in time - which Tuesday do you mean? 9:30 pm in what timezone? You can assume default values for these things if you use DateTimeFormatter, but from the comments it seems like you don't want to assume anything. You just want to store what is parsed.
You can write your own class that represents a day-of-week + hour + minutes only. If you implement TemporalAccessor, you will be able to parse and format it with DateTimeFormatter. Here is an example:
final class DayOfWeekLocalTime implements TemporalAccessor {
private final DayOfWeek dow;
private final int hour;
private final int minute;
private DayOfWeekLocalTime(DayOfWeek dow, int hour, int minute) {
this.dow = dow;
this.hour = hour;
this.minute = minute;
}
public static DayOfWeekLocalTime of(DayOfWeek dow, int hour, int minute) {
return new DayOfWeekLocalTime(dow, hour, minute);
}
public static DayOfWeekLocalTime parse(String s, DateTimeFormatter formatter) {
TemporalAccessor ta = formatter.parse(s);
return new DayOfWeekLocalTime(
DayOfWeek.of(ta.get(ChronoField.DAY_OF_WEEK)),
ta.get(ChronoField.HOUR_OF_DAY),
ta.get(ChronoField.MINUTE_OF_HOUR)
);
}
#Override
public String toString() {
// a default format
return DateTimeFormatter.ofPattern("EEE:HH:mm").format(this);
}
#Override
public boolean isSupported(TemporalField field) {
return field == ChronoField.DAY_OF_WEEK ||
field.getBaseUnit() == ChronoUnit.HOURS ||
field.getBaseUnit() == ChronoUnit.MINUTES ||
field == ChronoField.AMPM_OF_DAY;
}
#Override
public long getLong(TemporalField field) {
if (!isSupported(field)) {
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
if (field == ChronoField.DAY_OF_WEEK) {
return dow.getValue();
}
return field.getFrom(LocalTime.of(hour, minute));
}
// equals and hashcode omitted for brevity
}
To parse it:
DayOfWeekLocalTime.parse("Tue:21:30", DateTimeFormatter.ofPattern("EEE:HH:mm"));
Do not use java.util.date, as it has several negative aspects.
Use newer (since Java 8) JSR 310: Date Time API.
You can do:
DateTimeFormatter format1 = DateTimeFormatter.ofPattern("EEE HH:mm");
DateTimeFormatter format2 = DateTimeFormatter.ofPattern("EEEE HH:mm"); //gives you full name of the day
LocalDateTime ldt = LocalDateTime.now();
//if it's Thursday, 10:30
System.out.println(ldt.format(format1)); //prints Thu 10:30
System.out.println(ldt.format(format2)); //prints Thursday 10:30
Alternatively, use any other date object instead of .now() from the LocalDateTime API.
Some other references on why not to use java.util.date can be found here, here, here, and here.
i try to get a previous date of custom date that selected by a user but i cant find a way to do that
this is the code
calendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
#Override
public void onSelectedDayChange( #NonNull CalendarView view, int year, int month, int dayOfMonth ) {
finalDate = (dayOfMonth + 7) + "/" + (month - 3) + "/" + year;
try {
Date date = new SimpleDateFormat("dd/MM/yyyy").parse(finalDate);
} catch (ParseException e) {
e.printStackTrace();
}
}
});
so if i select 30/2/2020 the result is : (37/-1/2020)
java.time and ThreeTenABP
Consider using java.time, the modern Java date and time API, for your date work. Not least when you need to math on dates. I frankly find it much better suited than the old and outdated Calendar class, not to mention Date and SimpleDateFormat.
int year = 2020;
int month = Calendar.MARCH; // For demonstration only, don’t use Calendar in your code
int dayOfMonth = 30;
LocalDate selectedDate = LocalDate.of(year, month + 1, dayOfMonth);
LocalDate finalDate = selectedDate.minusMonths(3).plusDays(7);
System.out.println(finalDate);
Output:
2020-01-06
I believe that your Android date picker numbers months from 0 for January through 11 for December, so we need to add 1 to convert to the natural way that humans and LocalDate number months. When we start out from 30th March, we subtract 3 months and get 30th December, then add 7 days and get 6th January. We might also have done the math in the opposite order:
LocalDate finalDate = selectedDate.plusDays(7).minusMonths(3);
In this case it gave the same result, but since months have unequal lengths, it won’t always.
Isn't it because you are adding 7 to your day count and subtracting 3 from your month count? Try removing that and it should work better.
I have a date class and it has the following
public class Date {
public int month;
public int day;
public int year;
public Date(int m, int d, int y)
{
month = m;
day = d;
year = y;
}
public Date increase(int numberOfDays)
{
day += numberOfDays;
return this;
}
My question is what is the easiest way to do increasing of number of days to that given instance of Date? Like for example I have a created an instance of new Date(4,20,2016).increase(30); which would increase the given date addition 30 days. That would be sometime in May 19 I think. The method above should work if it's less than the max day of the month. But I haven't figure out how to do the calculation including the month and year. Like I added 365 days to that date would be 4/20/2017. Just an idea would be helpful. Thanks
use Java Calendar object instead. https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, 30); // add 30 days
date = cal.getTime();
using jcalendar you can add the dates try this example
Implementing this yourself is a suprisingly tricky task. More so since you are storing your Date as a separate month, year and day. You would have to store information about the number of days in every month, along with information about leap years. In short, trying to re-implement Date is not easy.
One solution to storing a "day, month, year" date before Java 8 came along was to use Joda. Using Joda's LocalDate class, you can do:
LocalDate date = LocalDate.now();
date = date.plusDays(30);
This functionality is now available in Java 8's java.time package, using the same LocalDate class name. Take a look at the source code for either package to see how it's implemented.
In short, LocalDate.plusDays() first converts the "month, day, year" date to a single number of days since the "epoch", using an algorithm that's around twenty lines long. Then, it adds the requested number of days to that number. Finally, it converts that number back to a "day, month, year" using another algorithm that's even longer.
I am a novice to Java programming using Netbeans. I have added jCalendar to my GUI to pick a date.
I have entered this line in Events -> "property change" code of jCalendar button,
Date date=jcalendar1.getDate();
So that I get the date immediately when it is changed. Am I right?
The purpose:
I want to find the difference in milliseconds from the afternoon (12:00 pm) of this date above to NOW (current date and time).
There are several programs showing the date difference but all have dates hardcoded and being a newbie i do not know how to replace it with the date that is picked. (also i am confused between the objects Date and Calendar, not able to understand the difference between them). For example, a piece from here:
http://www.java2s.com/Code/Java/Data-type/ReturnsaDatesetjusttoNoontotheclosestpossiblemillisecondoftheday.htm
if (day == null) day = new Date();
cal.setTime(day);
cal.set(Calendar.HOUR_OF_DAY, 12);
cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
return cal.getTime();
Here day is a Date object. How is cal (a calendar object) linked to it to enter the time. How should the cal object be defined first? How can I use this or anything else in your opinion for my program. A piece of code with detail comments will be more helpful
thanks!
Instead of using :
Date day = new Date();
Use:
Calendar cal = Calendar.getInstance();
cal.set (...);
Date date = new Date(cal.getTimeInMillis());
Worth abstracting this stuff out to a DateUtils class or similar, with something like the following:
public static Date create(int year, int month, int day, int hour, int minute, int second) {
return new Date(getTimeInMillis(year, month, day, hour, minute, second));
}
public static long getTimeInMillis(int year, int month, int day, int hour, int minute, int second, int milliseconds) {
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(year, month, day, hour, minute, second);
cal.set(Calendar.MILLISECOND, milliseconds);
return cal.getTimeInMillis();
}
Long time reader, first time poster.
In Android, capturing date from datepicker and storing as string in sqlite. Sorting by date doesn't work because they're strings (unless I'm doing it wrong.
I've googled this issue for ~5 days, and it looks like there should be a way to capture the date from the date picker, convert it to a Long, store it in sqlite as a Long, select and sort on the Long date value, then convert the Long back to a "mm/dd/yyyy" string for display. I've tried various combinations of parse statements, Date, FormatDate, etc. with no luck at all.
My actual application flow would be:
On activity start, get today's date and display it in button which calls the datepicker.
Capture new date from datepicker (if one is entered), save it as a long to sqlite.
On opening an activity showing a listview of records, select from sqlite with orderby on date (Long), convert Long to "mm/dd/yyyy" string for display in ListView.
If someone could point me at a code sample, it would be greatly appreciated - thanks!
Evan
Hours of hair-pulling later, the solution is sort of a mix of the answers given, and some other things:
// variables declared
private int mYear;
private int mMonth;
private int mDay;
// datepicker declared and listened for
private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
mYear = year;
mMonth = monthOfYear;
mDay = dayOfMonth;
updateDisplay();
}
};
// converting the datestring from the picker to a long:
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, mDay);
c.set(Calendar.MONTH, mMonth);
c.set(Calendar.YEAR, mYear);
Long lDate = c.getTime().getTime();
//The formatting that worked on the trip back from long to string
// (I spent hours with SimpleDateFormat strings, years that were off by 1500, etc.):
String DateFormatted = DateFormat.getDateFormat(getApplicationContext()).format(helper.getDate(c)); // helper.getDate(c) is just the passing back of the Long date from my SELECT statement
New to the forum - I tried to vote up as useful, but I don't have enough reputation points yet.
All Date objects in java are just Long values behind the scenes. You can get the Long value from a java Date object using getTime(), storing the resulting long value, and then initializing a new Date object using that long value in the constructor. Since the DatePicker gives interfaces to Day, Month and Year you should use the java Calendar class as an interim by creating a new Calendar object, setting the day, month and year before extracting a Date object and then a long value from the Date object.
I would say something along these lines:
DatePicker dp = blah blah;
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, dp.getDayOfMonth());
c.set(Calendar.MONTH, dp.getMonth());;
c.set(Calendar.YEAR, dp.getYear());
long l = c.getTime().getTime();
From here you can serialize your long value. Obviously then to reverse the process you pull the long value out, construct a Date object with the long value and then use a Calendar.setTime(Date) call before using the Calendar.get function to get the values to use on the DatePicker.init function, or utilizing a SimpleDateFormat object to get it prepped for display in a format like you described.
I'd just use a date as I think Calendar objects are a bit heavy for this task. Get your values from your DatePicker :
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
mYear = year;
mMonth = monthOfYear;
mDay = dayOfMonth;
updateDisplay();
}
Use the integers provide to the DatePicker to create a Date:
Date date = new Date(mYear, mMonth, mDay);
Then store and sort by the long value : date.getTime().
Alternatively, if you really must use strings for sorting dates, format them in yyyy/mm/dd format to ensure proper sorting, even then you need to watch out. I've just done some tests with SimpleDateFormat and it parses inappropriate date strings e.g. 2010/09/31 is interpreted as 2010/10/01.
When checking stuff like this I would always recommend running up some JUnit tests.