web-dev-qa-db-fra.com

Comment enregistrer et récupérer la date dans SharedPreferences

Je dois enregistrer quelques dates dans SharedPreferences dans Android et le récupérer. Je crée une application de rappel à l'aide de AlarmManager et je dois enregistrer la liste des dates futures . Il doit pouvoir être récupéré en millisecondes. J'ai d'abord pensé à calculer le temps entre le moment présent et le temps futur et à le stocker dans les préférences partagées. Mais cette méthode ne fonctionne pas car je dois l'utiliser pour AlarmManager.

52
Isuru Madusanka

Pour enregistrer et charger une date précise, vous pouvez utiliser la représentation long (nombre) d'un objet Date.

Exemple:

//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();

Vous pouvez l'utiliser pour enregistrer ou récupérer Date/Time les données de SharedPreferences comme ceci

Enregistrer:

SharedPreferences prefs = ...;
prefs.edit().putLong("time", date.getTime()).apply();

Relisez-le:

Date myDate = new Date(prefs.getLong("time", 0));

Modifier

Si vous souhaitez stocker le TimeZone en plus, vous pouvez écrire une méthode d'assistance à cet effet, quelque chose comme ça (je ne les ai pas testés, n'hésitez pas à le corriger, si quelque chose ne va pas):

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();
}
149
Balázs Édes

tl; dr

L'approche moderne utilise les classes Java.time et les chaînes ISO 8601 .

En train de lire.

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.

L'écriture.

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.

Si votre gestionnaire d'alarmes n'a pas encore été modernisé pour gérer les objets Java.time, convertissez les classes héritées et modernes en utilisant de nouvelles méthodes ajoutées aux anciennes classes.

Java.util.Date d = Java.util.Date.from( instant ) ;

…et…

Instant instant = d.toInstant() ;

Java.time

Les anciennes classes de date-heure gênantes ont été remplacées par les classes Java.time.

Pendant un moment en UTC, avec une résolution de nanosecondes, utilisez Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Vous ne voulez que des millisecondes pour vos besoins, donc tronquez toutes les microsecondes et nanosecondes.

Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;

Pour déterminer un moment par date et heure, il faut un fuseau horaire. Un fuseau horaire est crucial pour déterminer une date. Pour un moment donné, la date varie dans le monde par zone. Par exemple, quelques minutes après minuit à Paris France est un nouveau jour alors qu'il est encore "hier" à Montréal Québec .

Si aucun fuseau horaire n'est spécifié, la JVM applique implicitement son fuseau horaire par défaut actuel. Cette valeur par défaut peut changer à tout moment pendant l'exécution (!), Donc vos résultats peuvent varier. Mieux vaut spécifier votre fuseau horaire souhaité/prév explicitement comme argument.

Spécifiez un nom de fuseau horaire correct au format continent/region, tel que America/Montreal , Africa/Casablanca ou Pacific/Auckland. N'utilisez jamais l'abréviation de 3-4 lettres telle que EST ou IST car ils sont pas vrais fuseaux horaires, non standardisés, ni même uniques (!) .

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Si vous souhaitez utiliser le fuseau horaire par défaut de la JVM, demandez-le et passez-le en argument. S'il est omis, la valeur par défaut actuelle de la JVM est implicitement appliquée. Mieux vaut être explicite, car la valeur par défaut peut être modifiée à tout moment pendant l'exécution par n'importe quel code dans n'importe quel thread de n'importe quelle application au sein de la JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Ou spécifiez une date. Vous pouvez définir le mois par un nombre, avec une numérotation saine 1-12 pour janvier-décembre.

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.

Ou, mieux, utilisez les objets d'énumération Month prédéfinis, un pour chaque mois de l'année. Astuce: utilisez ces objets Month dans votre base de code plutôt qu'un simple nombre entier pour rendre votre code plus auto-documenté, garantir des valeurs valides et fournir type-safety .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

À combiner avec une heure du jour, un LocalTime.

LocalTime lt = LocalTime.of( 14 , 0 ) ;

Enveloppez le tout ensemble comme un objet ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

Ajustez en UTC en extrayant un Instant.

Instant instant = zdt.toInstant() ;

Extrayez le nombre de millisecondes souhaité depuis la référence Epoch du premier moment de 1970 en UTC. Encore une fois, sachez que tous les micros/nanos de votre Instant seront ignorés lors de l'extraction des millisecondes.

long milliseconds = instant.toEpochMilli() ;  // Be aware of potential data loss, ignoring any microseconds or nanoseconds. 

Lisez ces millisecondes depuis le stockage sous forme de texte en utilisant la classe Long .

long milliseconds = Long.getLong( incomingText ) ;
Instant instant = Instant.ofEpochMilli( milliseconds ) ;

Pour voir ce moment à travers l'objectif de l'horloge murale utilisée par les habitants d'une région particulière (un fuseau horaire), appliquez un ZoneId pour obtenir un ZonedDateTime.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Pour générer du texte représentant cette valeur, utilisez DateTimeFormatter.ofLocalizedDateTime pour localiser automatiquement.

Conseil: pensez à écrire vos valeurs de date-heure dans le stockage au format standard ISO 8601 plutôt qu'en nombre de millisecondes. Les millisecondes ne peuvent pas être lues de manière significative par les humains, ce qui rend le débogage et la surveillance délicats.

String output = instant.toString() ; 

2018-10-05T20: 28: 48.584Z

Instant instant = Instant.parse( 2018-10-05T20:28:48.584Z ) ;

À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent l'ancien hérité) gênant classes date-heure telles que Java.util.Date , Calendar , & SimpleDateFormat .

Le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Tutoriel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* Des classes.

Où obtenir les classes Java.time?

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour de futurs ajouts possibles à Java.time. Vous pouvez trouver ici des classes utiles telles que Interval , YearWeek , YearQuarter , et plus .

3
Basil Bourque

Tu peux le faire:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.US);

Pour enregistrer une date:

preferences .edit().putString("mydate", sdf.format(date)).apply();

À récupérer:

try{
    Date date = sdf.parse(preferences.getString("myDate", "defaultValue"));
    } catch (ParseException e) {
                e.printStackTrace();
                               }

J'espère que cela vous aidera.

3
Fanny BATCHO