Reputation: 3491
I'm working with time picker and date picker dialog in Android. For saving DATE and TIME I'm using INTEGER data type in Sqlite. So I made few utility functions to convert DATE from Date Picker Dialog to LONG(TIMESTAMP) format and converting those back to user readable DATE. But somehow they are giving me the wrong result.
//Date Picker OnDateSetListener
private DatePickerDialog.OnDateSetListener datePickerListener = new DatePickerDialog.OnDateSetListener(){
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
String dateText = getTimeString(year,monthOfYear,dayOfMonth);
long date = Utility.getDateLong(year,monthOfYear,dayOfMonth);
taskModel.setEndDate(date);
endDateView.setText(dateText);
}
};
private String getTimeString(int year, int monthOfYear, int dayOfMonth){
Log.i("set_date",monthOfYear+"");
String yearText = String.valueOf(year);
String monthText = String.valueOf(monthOfYear);
String dayText = String.valueOf(dayOfMonth);
return dayText+"/"+monthText+"/"+yearText;
}
//Utility Functions
//Getting long(TIMESTAMP) from DATE
public static long getDateLong(int year, int month, int day){
Calendar calendar = new GregorianCalendar(year, month, day);
Date date = calendar.getTime();
long timeStamp = date.getTime();
return timeStamp;
}
//Converting TIMESTAMP to DATE
public static String getDateFromLongValue(long d){
Date date = new Date(d);
//Calendar calendar = new GregorianCalendar();
//calendar.setTimeInMillis(d);
//return calendar.get(Calendar.DAY_OF_MONTH)+"/"+calendar.get(Calendar.MONTH)+"/"+calendar.get(Calendar.YEAR);
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
String formattedDate = dateFormat.format(date);
return formattedDate;
}
I'm getting the wrong TIMESTAMP for the DATE that I entered. For example if the enterd DATE is 09-06-2016("dd-MM-yyyy") the converted long value is -876215232 which when converted back to date gives 22-12-1969.
Moreover when I'm selecting the DATE from picker I'm getting wrong month. i.e if I'm selecting 9th;July;2016, The monthOfYear property I'm getting 6 instead of 7. Can someone please point the mistake.
Upvotes: 0
Views: 804
Reputation: 340350
LocalDate localDate = LocalDate.of( 2016 , 1 , 31 ); // 1 = January.
LocalDate
counts months as you would expect: 1-12.YYYY-MM-DD
text rather than as timestamp.The Answer by MPelletier is correct, you did not follow the documentation telling you that month is zero-based counting (0-11) rather than one-based (1-12). Crazy behavior, yes. One of many reasons to avoid these poorly designed old date-time classes bundled with the earliest versions of Java.
Instead you should be using the java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
& java.util.Calendar
. See Oracle Tutorial. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
LocalDate
For a date-only value without time-of-day and without time zone, use the LocalDate
class. The month number is sane, 1-12.
LocalDate localDate = LocalDate.of( 2016 , 1 , 31 );
Or use the handy Month
enum.
LocalDate localDate = LocalDate.of( 2016 , Month.JANUARY , 31 );
You can interrogate for each part, year, month, and day-of-month.
int year = localDate.getYear();
int month = localDate.getMonthValue();
int dayOfMonth = localDate.getDayOfMonth();
When capturing the current date, be sure to specify a time zone. For any given moment the date varies around the globe by zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneID );
Using a count-of-milliseconds-from-epoch does not make sense for a date-only value. Given that SQLite has no true data types, and nothing to support SQL standard DATE columns, I suggest storing a String that represents the date value. Specifically, create a String in the formats defined by the ISO 8601 standard. The java.time classes use this standard’s formats by default when parsing and generating Strings. The standard format of YYYY-MM-DD
happens to sort alphabetically as chronological.
String string = localDate.toString(); // 2016-01-31
LocalDate localDate = LocalDate.parse( string );
If using JDBC 4.2 compliant driver, you may be able to pass the LocalDate
via getObject
/setObject
on a PreparedStatement
.
So LocalDate
compared to the old classes is:
Upvotes: 2
Reputation: 16709
Make sure the value you pass for the month to the GregorianCalendar
constructor is 0-based as documented here.
Upvotes: 2