在Java / Android中使用公历时获得错误的时间戳值



我正在使用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.Datejava.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)
  • 更易于使用字符串(直接解析/生成标准格式)
  • 真正表示仅日期值

相关内容

  • 没有找到相关文章

最新更新