I need to save a few dates in SharedPreferences
in android and retrieve it. I am building reminder app using AlarmManager
and I need to save list of future dates. It must be able to retrieve as milliseconds. First I thought to calculate time between today now time and future time and store in shared preference. But that method is not working since I need to use it for AlarmManager
.
Shared Preferences allow you to save and retrieve data in the form of key,value pair. In order to use shared preferences, you have to call a method getSharedPreferences() that returns a SharedPreference instance pointing to the file that contains the values of preferences.
getAll(): This method is used to retrieve all values from the preferences.
How to pass data from one activity to another in Android using shared preferences? Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.
and this is how you can retrieve the values. SharedPreferences shared = getSharedPreferences(PREF_NAME, MODE_PRIVATE); String channel = (shared. getString(keyChannel, "")); Also be aware that you can do so in a non-Activity class too but the only condition is that you need to pass the context of the Activity.
To save and load accurate date, you could use the long
(number) representation of a Date
object.
Example:
//getting the current time in milliseconds, and creating a Date object from it: Date date = new Date(System.currentTimeMillis()); //or simply new Date(); //converting it back to a milliseconds representation: long millis = date.getTime();
You can use this to save or retrieve Date
/Time
data from SharedPreferences
like this
Save:
SharedPreferences prefs = ...; prefs.edit().putLong("time", date.getTime()).apply();
Read it back:
Date myDate = new Date(prefs.getLong("time", 0));
Edit
If you want to store the TimeZone
additionaly, you could write some helper method for that purpose, something like this (I have not tested them, feel free to correct it, if something is wrong):
public static Date getDate(final SharedPreferences prefs, final String key, final Date defValue) { if (!prefs.contains(key + "_value") || !prefs.contains(key + "_zone")) { return defValue; } Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(prefs.getLong(key + "_value", 0)); calendar.setTimeZone(TimeZone.getTimeZone(prefs.getString(key + "_zone", TimeZone.getDefault().getID()))); return calendar.getTime(); } public static void putDate(final SharedPreferences prefs, final String key, final Date date, final TimeZone zone) { prefs.edit().putLong(key + "_value", date.getTime()).apply(); prefs.edit().putString(key + "_zone", zone.getID()).apply(); }
The modern approach uses java.time classes and ISO 8601 strings.
Reading.
Instant // Represent a moment in UTC with a resolution of nanoseconds. .ofEpochMilli( Long.getLong( incomingText ) ) // Returns a `Instant` object. .atZone( // Adjust from UTC to some time zone. Same moment, same point on the timeline, different wall-clock time. ZoneId.of( "Europe/Paris" ) ) // Returns a `ZonedDateTime` object.
Writing.
ZonedDateTime .of( LocalDate.of( 2018 , Month.JANUARY , 23 ) , LocalTime.of( 15 , 35 ) , ZoneId.of( "Europe/Paris" ) ) // Returns a `ZonedDateTime` object. .toInstant() // Returns an `Instant`. Adjust from a time zone to UTC. Same moment, same point on the timeline, different wall-clock time. .toEpochMilli() // Returns a `long` integer number primitive. Any microseconds or nanoseconds are ignored, of course.
If your alarm manager has not yet been modernized to handle java.time objects, convert between legacy & modern classes using new methods added to the old classes.
java.util.Date d = java.util.Date.from( instant ) ;
…and…
Instant instant = d.toInstant() ;
The troublesome old date-time classes were supplanted by the java.time classes.
For a moment in UTC, with a resolution of nanoseconds, use Instant
.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
You want only milliseconds for your needs, so truncate any microseconds & nanoseconds.
Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;
To determine a moment by date and time-of-day requires a time zone. A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ; LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month
enum objects pre-defined, one for each month of the year. Tip: Use these Month
objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Combine with a time-of-day, a LocalTime
.
LocalTime lt = LocalTime.of( 14 , 0 ) ;
Wrap it all together as a ZonedDateTime
object.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
Adjust to UTC by extracting a Instant
.
Instant instant = zdt.toInstant() ;
Extract your desired count-of-milliseconds since the epoch reference of first moment of 1970 in UTC. Again, be aware that any micros/nanos in your Instant
will be ignored when extracting milliseconds.
long milliseconds = instant.toEpochMilli() ; // Be aware of potential data loss, ignoring any microseconds or nanoseconds.
Read those milliseconds back from storage as text using the Long
class.
long milliseconds = Long.getLong( incomingText ) ; Instant instant = Instant.ofEpochMilli( milliseconds ) ;
To see that moment through the lens of the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId
to get a ZonedDateTime
.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt = instant.atZone( z ) ;
To generate text representing that value, use DateTimeFormatter.ofLocalizedDateTime
to automatically localize.
Tip: Consider writing your date-time values to storage in standard ISO 8601 format rather than as a count-of-milliseconds. The milliseconds cannot be read meaningfully by humans, making debugging & monitoring tricky.
String output = instant.toString() ;
2018-10-05T20:28:48.584Z
Instant instant = Instant.parse( 2018-10-05T20:28:48.584Z ) ;
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With