从 Java 中的给定日期对象构造字符串

Constructing String from given Date object in Java

我正在使用一个日历和一个 NoSQL 数据库,只要用户点击日历中的特定日期,它就会存储数据。

我目前正在使用 "YYYYMMDD"

格式的节点存储数据

例如-

20190823:
       generatedKeyofUser: <user's data> 
20190824:
       generatedKeyofAnotherUser: <another's data>

我希望不仅能获取用户点击的日期,还能获取最多 4 天前的点击日期。

例如,如果用户点击了 2019 年 1 月 2 日,我希望查询具有以下日期的数据库 "20190102", "20190101, "20181231", "20181230"

目前我正在以上述格式构建字符串 -

calendarView.setOnDayClickListener(event-> {
            Calendar clickedDate = event.getCalendar();
            Intent intent = new Intent(CalendarActivity.this, DateActivity.class);
            SharedPreferences.Editor editor = sp.edit();
            String year = Integer.toString(clickedDate.get(Calendar.YEAR));
            String month = new DecimalFormat("00").format(clickedDate.get(Calendar.MONTH) + 1);
            String day = new DecimalFormat("00").format(clickedDate.get(Calendar.DAY_OF_MONTH));
            editor.putString("year", year);
            editor.putString("month", month);
            editor.putString("day",day );
            editor.apply();
            startActivity(intent);
        });

将其发送给另一个 activity,以便它可以从数据库中获取用户数据。

编辑: 我编辑了我的代码,如下所示 -

calendarView.setOnDayClickListener(event-> {
            Intent intent = new Intent(CalendarActivity.this, DateActivity.class);
            SharedPreferences.Editor editor = sp.edit();

            // Chosen date
            Calendar clickedDate = event.getCalendar();

            // Yesterday's chosen date
            Calendar clickedDateYesterday = (Calendar) clickedDate.clone();
            clickedDateYesterday.add(Calendar.DAY_OF_YEAR, -1);

            // Two days ago from chosen date
            Calendar clickedDateTwoDaysAgo = (Calendar) clickedDate.clone();
            clickedDateTwoDaysAgo.add(Calendar.DAY_OF_YEAR, -2);

            // Three days ago from chosen date
            Calendar clickedDateThreeDaysAgo = (Calendar) clickedDate.clone();
            clickedDateYesterday.add(Calendar.DAY_OF_YEAR, -3);

            SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
            String formattedChosenDate = formatter.format(clickedDate.getTime());
            String formattedYesterdayChosenDate = formatter.format(clickedDateYesterday.getTime());
            String formattedTwoDaysAgoChosenDate = formatter.format(clickedDateTwoDaysAgo.getTime());
            String formattedThreeDaysAgoChosenDate = formatter.format(clickedDateThreeDaysAgo.getTime());
            Log.i("dates", "Chosen Date - " + formattedChosenDate + " ; Yesterday - " + formattedYesterdayChosenDate + " ; Two Days Ago - "+
                    formattedTwoDaysAgoChosenDate + " ; Three Days Ago - " + formattedThreeDaysAgoChosenDate);
            editor.apply();
            startActivity(intent);
        });

但是日志显示

Chosen Date - 20190808 ; Yesterday - 20190804 ; Two Days Ago - 20190806 ; Three Days Ago - 20190808

而不是

Chosen Date - 20190808 ; Yesterday - 20190807 ; Two Days Ago - 20190806 ; Three Days Ago - 20190805

首先,要获取范围,您可以克隆当前选择并删除您想要的天数(在您的示例中为 4 天)。

Calendar clickedDate = event.getCalendar();
Calendar offsetDate = clickedDate.clone();
offset.add(Calendar.DAY_OF_YEAR, -4)

要根据需要格式化值,您可以创建 DateFormater 来实现。

SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String initialDate = formatter.format(offsetDate.getTime());
String finalDate = formatter.format(clickedDate.getTime());

如果你挥手从范围内的日期中获取所有字符串,你可以只运行一个"for",迭代并生成两个值之间的值,使用.add 功能如我在第一个示例中所示。

tl;博士

( ( GregorianCalendar ) myCalendar )   // Cast from interface to likely concrete class.
.toZonedDateTime()                     // Convert from legacy class to modern. Returns a `ZonedDateTime` object.
.minusDays( 1 )                        // Subtract a day to get same time-of-day yesterday. Returns a new `ZonedDateTime` object.
.format(                               // Generate text.
    DateTimeFormatter.BASIC_ISO_DATE   // Specify standard ISO 8601 "basic" format of YYYYMMDD.
)                                      // Returns a `String`. 

20190807

……和……

GregorianCalendar.from (                    // Convert from modern `ZonedDateTime` class to legacy class.
    ( ( GregorianCalendar ) myCalendar )    // Cast from interface to likely concrete class.
    .toZonedDateTime()                      // Convert from legacy class too modern. Returns a `ZonedDateTime` object.
    .minusDays( 1 )                         // Subtract a day to get same time-of-day yesterday in the same zone. Returns a new `ZonedDateTime` object.
)                                           // Returns a `GregorianCalendar` object, which is also a `Calendar` object.

避免遗留日期时间 classes

可怕的遗留日期时间 classes,例如 CalendarSimpleDateFormat 多年前被现代的 java.time classes 在 JSR 310 中定义。

显然您使用的是尚未更新为 java.time 的旧日历小部件。如果是这样,通过调用添加到旧 classes 的新 to…/from… 方法进行转换。

ZonedDateTime

要从Calendar转换成ZonedDateTime,先转换成GregorianCalendar,一般的具体实现。

GregorianCalendar gc = ( GregorianCalendar ) c ;

现在转换。

ZonedDateTime zdt = gc.toZonedDateTime() ;

您显然只想要日期,没有时间和时区。所以提取一个LocalDate.

LocalDate ld = zdt.toLocalDate() ;

使用 DateTimeFormatter class. Your desired format YYYYMMDD happens to be the “basic” variant of the standard ISO 8601 format YYYY-MM-DD. Your desired formatting pattern is already defined as DateTimeFormatter.BASIC_ISO_DATE 生成该日期值的文本表示。

String output = ld.format( DateTimeFormatter.BASIC_ISO_DATE ) ;

日期数学

你还要昨天和前天。

LocalDate yesterday = ld.minusDays( 1 ) ;
LocalDate dayBeforeYesterday = ld.minusDays( 2 ) ;

一天开始

如果要转换回 Calendar 对象,您需要首先考虑一天中的时间。 A Calendar 表示一个时刻,一个在时区上下文中带有时间的日期。

如果您想获得当天的第一个时刻,让java.time确定那个时刻。不要假设一天从 00:00 开始。由于夏令时 (DST) 等异常情况,某些时区某些日期的某些日子可能会在另一个时间开始,例如 01:00。

对于必要的区域,我们可以从 GregorianCalendar 中提取在我们的 ZonedDateTime 对象中使用的区域。

ZoneId z = zdt.getZone() ;
ZonedDateTime startOfYesterday = yesterday.atStartOfDay( z ) ;

转换为 GregorianCalendar.

 GregorianCalendar gc = GregorianCalendar.from( startOfYesterday ) ;

gc(也是 CalendarGregorianCalendar)传递给您的日历小部件。

如果您想要与我们开始时 zdt 相同的一天中的时间,而不是一天中的第一时刻,请对该对象进行日期计算。

ZonedDateTime zdtYesterdaySameTime = zdt.minusDays( 1 ) ;
ZonedDateTime zdtDayBeforeYesterdaySameTime = zdt.minusDays( 2 ) ;

提示:尝试查找使用 LocalDate class 的日历小部件,如果您只关心日期而没有时间和时区。



关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规格为 JSR 310.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?