我正在使用Android中的时间选择器和日期选择器对话框。为了保存日期和时间,我在 Sqlite 中使用了整数数据类型。所以我做了一些实用程序函数来将日期从日期选择器对话框转换为LONG(时间戳)格式,并将其转换回用户可读的DATE。但不知何故,他们给了我错误的结果。
//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;
}
我输入的日期的时间戳错误。例如,如果输入的 DATE 是 09-06-2016("dd-MM-yyyy"),则转换后的多头值为 -876215232,当转换回日期时,该值为 22-12-1969。
此外,当我从选择器中选择日期时,我得到错误的月份。 即如果我选择第 9 个;2016 年 7 月,年度月份属性我得到 6 而不是 7。有人可以指出错误吗?
确保将月份的值传递给GregorianCalendar
构造函数的值从 0 开始,如此处所述。
tl;dr
LocalDate localDate = LocalDate.of( 2016 , 1 , 31 ); // 1 = January.
- 使用 java.time 类。
LocalDate
如您所料计算月数:1-12。 - 存储为
YYYY-MM-DD
文本,而不是时间戳。
详
MPelletier 的答案是正确的,您没有按照文档告诉您月份是从零开始计数 (0-11) 而不是从 1 开始计数 (1-12)。疯狂的行为,是的。避免这些设计不佳的旧日期时间类与最早的 Java 版本捆绑在一起的众多原因之一。
java.time
相反,您应该使用Java 8及更高版本中内置的java.time框架。这些类取代了旧的麻烦的日期时间类,如java.util.Date
和java.util.Calendar
。请参阅甲骨文教程。Java.time的大部分功能在ThreeTen-Backport中向后移植到Java 6和7,并在ThreeTenABP中进一步适应Android。
LocalDate
对于没有时间且没有时区的仅日期值,请使用 LocalDate
类。月份数字是理智的,1-12。
LocalDate localDate = LocalDate.of( 2016 , 1 , 31 );
或者使用方便的Month
枚举。
LocalDate localDate = LocalDate.of( 2016 , Month.JANUARY , 31 );
部分日期
您可以询问每个部分、年、月和月中的某天。
int year = localDate.getYear();
int month = localDate.getMonthValue();
int dayOfMonth = localDate.getDayOfMonth();
时区
捕获当前日期时,请务必指定时区。对于任何给定时刻,日期因区域而异。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneID );
ISO 8601
认证对于仅日期值,使用从纪元开始的毫秒计数没有意义。鉴于SQLite没有真正的数据类型,也没有支持SQL标准DATE列的内容,我建议存储一个表示日期值的字符串。具体来说,以 ISO 8601 标准定义的格式创建字符串。java.time 类在解析和生成字符串时默认使用此标准的格式。YYYY-MM-DD
的标准格式恰好按时间顺序按字母顺序排序。
String string = localDate.toString(); // 2016-01-31
LocalDate localDate = LocalDate.parse( string );
如果使用符合JDBC 4.2的驱动程序,则可以通过PreparedStatement
上的getObject
/setObject
传递LocalDate
。
总结
因此,与旧类相比LocalDate
是:
- 更合乎逻辑(理智的月份计数 1-12)
- 更易于使用字符串(直接解析/生成标准格式)
- 真正表示仅日期值