【问题标题】:Getting wrong value of time stamp while using Gregorian Calendar in Java/Android在 Java/Android 中使用公历时获取错误的时间戳值
【发布时间】:2016-07-12 18:06:07
【问题描述】:

我正在使用 Android 中的时间选择器和日期选择器对话框。为了保存 DATE 和 TIME,我在 Sqlite 中使用 INTEGER 数据类型。所以我做了一些实用函数来将日期选择器对话框中的 DATE 转换为 LONG(TIMESTAMP) 格式,并将它们转换回用户可读的 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 的 TIMESTAMP 错误。例如,如果输入的 DATE 是 09-06-2016("dd-MM-yyyy"),则转换后的 long 值为 -876215232,当转换回日期时会得到 22-12-1969。

此外,当我从选择器中选择 DATE 时,我弄错了月份。即,如果我选择 9th;July;2016, monthOfYear 属性,我将得到 6 而不是 7。 谁能指出错误。

【问题讨论】:

  • 公历月份从 0 到 11 开始,即 1 月是该日历中一年中的第 0 个月。检查 Java 文档。这就是为什么你得到 6 而不是正确的 7。

标签: java android sqlite date datetime


【解决方案1】:

确保您传递给 GregorianCalendar 构造函数的月份值是从 0 开始的,如文档中的 here 所述。

【讨论】:

    【解决方案2】:

    tl;博士

    LocalDate localDate = LocalDate.of( 2016 , 1 , 31 );  // 1 = January.
    
    • 使用java.time 类。 LocalDate 按您的预期计算月份:1-12。
    • 存储为YYYY-MM-DD 文本而不是时间戳。

    详情

    Answer by MPelletier 是正确的,您没有按照文档告诉您该月份是从零开始计数 (0-11) 而不是从一开始 (1-12)。疯狂的行为,是的。 许多原因之一是避免将这些设计不佳的旧日期时间类与 Java 的最早版本捆绑在一起。

    java.time

    相反,您应该使用 Java 8 及更高版本中内置的 java.time 框架。这些类取代了旧的麻烦的日期时间类,例如java.util.Datejava.util.Calendar。见Oracle Tutorial。大部分 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

    使用来自-epoch 的毫秒计数对于仅日期值没有意义。鉴于 SQLite 有 no true data types,并且没有任何东西支持 SQL 标准 DATE 列,我建议存储一个表示日期值的字符串。具体来说,以 ISO 8601 标准定义的格式创建一个字符串。 java.time 类在解析和生成字符串时默认使用此标准的格式。 YYYY-MM-DD 的标准格式恰好按时间顺序按字母顺序排序。

    String string = localDate.toString(); // 2016-01-31
    LocalDate localDate = LocalDate.parse( string );
    

    如果使用符合 JDBC 4.2 的驱动程序,您可以通过 getObject/setObjectPreparedStatement 上传递 LocalDate

    总结

    所以LocalDate与旧类相比是:

    • 更合乎逻辑(理智的月份计数 1-12)
    • 使用字符串更容易(直接解析/生成标准格式)
    • 真正代表一个仅限日期的值

    【讨论】:

    • 如果我以字符串形式存储 LocalDateTime,它如何用于执行日期操作,例如查找两个日期之间的时间间隔?
    猜你喜欢
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多