web-dev-qa-db-fra.com

Conversion de chaîne en Instant

J'essaie de convertir date/heure dans chaîne en instantané à l'aide de Java 8 ou du package utils.

Pour par exemple.

String requestTime = "04:30 PM, Sat 5/12/2018";

à

Instant reqInstant should result in 2018-05-12T20:30:00.000Z

reqString est dans le fuseau horaire Amérique/Toronto.

C'est ce que j'ai essayé

 String strReqDelTime = "04:30 PM, Sat 5/12/2018";
 Date date = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy").parse(requestTime);
 Instant reqInstant = date.toInstant();

Le code ci-dessus donne "2018-05-12T23:30:00Z".

Toute aide est appréciée.

5
Venky

tl; dr

  • Corrigez votre modèle de formatage pour le mois et le jour non rembourrés.
  • Utilisez uniquement les classes Java.time, jamais les classes héritées.

Exemple élaboré:

LocalDateTime.parse(                   // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
    "04:30 PM, Sat 5/12/2018" ,        // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the Java.time classes use the standard formats by default when parsing/generating strings.
    DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US )  // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values.
)                                      // Returns a `LocalDateTime` object.
.atZone(                               // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.
    ZoneId.of( "America/Toronto" )     // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`. 
)                                      // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto].
.toInstant()                           // Extract a `Instant` object, always in UTC by definition.
.toString()                            // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*.

2018-05-12T20: 30: 00Z

Utiliser un modèle de formatage à un chiffre

Vous avez utilisé MM dans votre modèle de formatage, pour signifier que toute valeur à un chiffre (mois janvier à septembre) apparaît avec un zéro précédé et complété.

Mais votre entrée manque ce zéro capitalisé. Utilisez donc une seule variable M.

Idem pour le jour du mois, j'attends: d plutôt que dd.

Utilisez uniquement Java.time

Vous utilisez d'anciennes classes de date-heure défectueuses (Date & SimpleDateFormat) qui ont été supplantées il y a des années par les classes Java.time. Les nouvelles classes supplantent entièrement les anciennes. Pas besoin de mélanger l'héritage et le moderne.

LocalDateTime

Analyser comme un LocalDateTime parce que votre chaîne d'entrée ne contient aucun indicateur de fuseau horaire ou offset par rapport à UTC . Une telle valeur est pas un moment, pas un point sur la timeline. Il ne s'agit que d'un ensemble de potentiels moments sur une plage d'environ 26 à 27 heures.

String input = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US );  // Specify locale to determine human language and cultural norms used in translating that input string.
LocalDateTime ldt = LocalDateTime.parse( input , f );

ldt.toString (): 2018-05-12T16: 30

ZonedDateTime

Si vous savez avec certitude que l'entrée était censée représenter un moment en utilisant l'horloge cadrée utilisée par les habitants de la région de Toronto au Canada, appliquez une ZoneId pour obtenir un objet ZonedDateTime .

L'affectation d'un fuseau horaire donne un sens à votre LocalDateTime sans zonage. Nous avons maintenant un moment, un point sur la chronologie.

ZoneId z = ZoneId.of( "America/Toronto" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline.

zdt.toString (): 2018-05-12T16: 30-04: 00 [America/Toronto]

Instant

Pour voir le même moment que UTC , extrayez un Instant . Même moment, heure différente de l'horloge murale.

Instant instant = zdt.toInstant() ;

instant.toString (): 2018-05-12T20: 30: 00Z


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .

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

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

Où obtenir les classes Java.time? 

  • Java SE 8 , Java SE 9 , Java SE 10 , et versions ultérieures
    • Intégré. 
    • Une partie de l'API Java standard avec une implémentation fournie.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité Java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Les versions ultérieures d'Android regroupent des implémentations des classes Java.time.
    • Pour les anciens Android (<26), le projet ThreeTenABP s’adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

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

14
Basil Bourque

Il semble que le fuseau horaire de votre ordinateur (serveur) soit l'heure d'été des États-Unis pour le Pacifique américain (GMT-7), mais vous attendez des résultats pour l'heure d'été des États-Unis d'Amérique (GMT-4).

Instant.toString () renvoie l'heure UTC (GMT + 0) au format ISO-8601. ('Z' à la fin signifie UTC).

Menaces SimpleDateFormat DateTime Chaîne dans le fuseau horaire par défaut de l'ordinateur lorsqu'il n'est pas spécifié. Et votre entrée ne spécifie pas le fuseau horaire.

Vous devez donc définir le fuseau horaire de votre saisie.

PS. sur mon ordinateur dans l’est de l’heure d’été, votre code me donne les résultats que vous attendiez.

0
Vadim