Reputation: 327
I'm working with a calendar and a NoSQL database that stores data whenever a user clicks on a specific date in the calendar.
I'm currently storing data using nodes in format of "YYYYMMDD"
e.g. -
20190823:
generatedKeyofUser: <user's data>
20190824:
generatedKeyofAnotherUser: <another's data>
I wish to be able to fetch not only the date the user has clicked on but also up to 4 days prior.
for example, if the user clicked on Jan 2nd 2019, I wish to query the database with the following dates "20190102", "20190101, "20181231", "20181230"
Currently I'm constructing a string in said format like so -
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);
});
sending it to the other activity so it can fetch the user's data from the database.
Edit: I edited my code as shown below -
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);
});
But the Log shows
Chosen Date - 20190808 ; Yesterday - 20190804 ; Two Days Ago - 20190806 ; Three Days Ago - 20190808
instead of
Chosen Date - 20190808 ; Yesterday - 20190807 ; Two Days Ago - 20190806 ; Three Days Ago - 20190805
Upvotes: 0
Views: 78
Reputation: 340200
( ( 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
…and…
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.
The terrible legacy date-time classes such as Calendar
and SimpleDateFormat
were supplanted years ago by the modern java.time classes defined in JSR 310.
Apparently you are using an old calendaring widget that has yet to be updated to java.time. If so, convert by calling new to…
/from…
methods added to the old classes.
ZonedDateTime
To convert from Calendar
to ZonedDateTime
, first cast to GregorianCalendar
, the common concrete implementation.
GregorianCalendar gc = ( GregorianCalendar ) c ;
Now convert.
ZonedDateTime zdt = gc.toZonedDateTime() ;
You want only the date apparently, without the time-of-day and without the time zone. So extract a LocalDate
.
LocalDate ld = zdt.toLocalDate() ;
Generate a textual representation of that date value using 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 ) ;
You also want yesterday and day before that.
LocalDate yesterday = ld.minusDays( 1 ) ;
LocalDate dayBeforeYesterday = ld.minusDays( 2 ) ;
If you want to convert back to a Calendar
object, you need to think first about the time-of-day. A Calendar
represents a moment, a date with time-of-day in the context of a time zone.
If you want to get the first moment of the day, let java.time determine that moment. Do not assume the day starts at 00:00. Some days on some dates in some time zones may start at another time such as 01:00 because of anomalies such as Daylight Saving Time (DST).
For the necessary zone, we can extract the zone used in our ZonedDateTime
object converted from the GregorianCalendar
.
ZoneId z = zdt.getZone() ;
ZonedDateTime startOfYesterday = yesterday.atStartOfDay( z ) ;
Convert to GregorianCalendar
.
GregorianCalendar gc = GregorianCalendar.from( startOfYesterday ) ;
Pass that gc
(which is also a Calendar
as well as a GregorianCalendar
) to your calendaring widget.
If instead of first moment of the day, if you had wanted the same time-of-day as zdt
we started with, do the date math on that object.
ZonedDateTime zdtYesterdaySameTime = zdt.minusDays( 1 ) ;
ZonedDateTime zdtDayBeforeYesterdaySameTime = zdt.minusDays( 2 ) ;
Tip: Try to find a calendaring widget that uses LocalDate
class, if the date is all you care about without time-of-day and without time zone.
The 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
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
Upvotes: 2
Reputation: 146
First of all, to get the range, you can clone the current selection and remove the days you want (in your example, 4 days).
Calendar clickedDate = event.getCalendar();
Calendar offsetDate = clickedDate.clone();
offset.add(Calendar.DAY_OF_YEAR, -4)
To format the value as you want, you can create a DateFormater to achieve that.
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String initialDate = formatter.format(offsetDate.getTime());
String finalDate = formatter.format(clickedDate.getTime());
If you wave to get all strings from the dates in the range, you can just run a "for", to iterate and generate the values between the two values, using the .add
function as I showed in the first example.
Upvotes: 1