Je n'arrive pas à bien suivre votre code. Voici donc quelques conseils généraux. Je dois dire d'emblée que la gestion des rendez-vous et des horaires est un domaine étonnamment compliqué.
Vous semblez vous concentrer sur les chaînes de caractères plutôt que sur les types de données appropriés, un problème courant chez les nouveaux programmeurs. Apprenez à utiliser des objets intelligents, pas des chaînes de caractères idiotes . Notez qu'aucun des codes présentés ci-dessous n'implique de chaînes de caractères, sauf pour la présentation aux utilisateurs. Les valeurs sont échangées avec la base de données sous forme d'objets, sans l'utilisation de chaînes de caractères.
Java offre un assortiment de classes de date et d'heure à la pointe de l'industrie, dans la catégorie java.time paquets. Alors utilisez-les. LocalTime
représente une heure du jour. LocalDate
représente une date uniquement, sans heure du jour, et sans fuseau horaire.
Pour la saisie de données sur l'heure du rendez-vous, vous devez collecter une heure et une minute. Travailler en interne avec une horloge de 24 heures LocalTime
objets.
List< LocalTime > hourTimes =
List.of(
LocalTime.of( 8 , 0 ) ,
LocalTime.of( 9 , 0 ) ,
LocalTime.of( 10 , 0 ) ,
LocalTime.of( 11 , 0 ) ,
LocalTime.of( 12 , 0 ) ,
LocalTime.of( 13 , 0 ) ,
LocalTime.of( 14 , 0 ) ,
LocalTime.of( 15 , 0 ) ,
LocalTime.of( 16 , 0 )
)
;
Si votre public s'attend à un Horloge de 12 heures présentent leur affichage avec un formateur personnalisé. Si votre public s'attend à une horloge de 12 heures, présentez leur écran avec un formateur personnalisé.
Locale locale = Locale.US ;
DateTimeFormatter formatterHourOfDay = DateTimeFormatter.ofPattern ( "h a" ).withLocale ( locale ) ;
String output = hourTimes.get( 7 ).format( formatterHourOfDay ) ;
Voir similaire code exécuté en direct sur IdeOne.com .
3 PM
Notez que java.time utilise objets immuables . Vous pouvez donc utiliser librement le LocalTime
directement à partir de la liste principale, sans qu'il soit nécessaire de copier, ni de s'inquiéter que ses valeurs soient modifiées sous vos pieds. Cela signifie également que vous pouvez utiliser java.time à travers les threads, car ils sont conçus pour être Sécurité des fils .
Conservez une liste des procès-verbaux possibles.
List< Integer > minutes = List.of( 0 , 15 , 30 , 45 ) ;
Dans votre interface utilisateur, laissez l'utilisateur choisir l'une de ces quatre valeurs, qui sera associée à son choix parmi les options suivantes hourTimes
ci-dessus.
Rassemblez ces valeurs en fonction de l'heure de la journée pour obtenir une nouvelle valeur. LocalTime
.
LocalTime localTime = hourTimes.get( 7 ).plusMinutes( minutes.get( 2 ) ) ; // Adding 0, 15, 30, or 45 minutes to the on-the-hour `LocalTime` object, resulting in another `LocalTime` object.
Combinez l'heure du jour avec votre date prévue pour obtenir une LocalDateTime
objet.
LocalDate localDate = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
LocalDateTime localDateTime = LocalDateTime.of( localDate , localTime ) ;
Stockez-le dans une colonne de base de données de type standard SQL. TIMESTAMP WITHOUT TIME ZONE
. (c'était "SANS", pas "AVEC")
Il est généralement préférable d'utiliser déclarations préparées en SQL plutôt que de combiner des chaînes de caractères.
myPreparedStatement.setObject( … , localDateTime ) ;
En outre, enregistrez le fuseau horaire prévu pour ce rendez-vous. Il existe un type de données en Java pour cela, ZoneId
. Mais pas en SQL. Enregistrez donc le nom de la zone en tant que texte dans votre base de données.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
…
myPreparedStatement.setObject( … , z.toString() ) ; // Record name of zone as text.
D'ailleurs, il n'est pas nécessaire de transmettre la date de création ou de dernière mise à jour de l'enregistrement. Vous devriez configurer votre base de données pour qu'elle définisse ces valeurs automatiquement du côté du serveur.
Séparez votre logique commerciale de votre interface utilisateur. Remarquez qu'aucun de mes codes ci-dessus ne concerne JavaFX .
Définissez une classe uniquement pour le rendez-vous. Cette classe ne doit connaître que les besoins d'un rendez-vous, les règles de gestion de ce qui définit un rendez-vous valide. Cette classe ne doit rien savoir de la base de données, ni de l'interface utilisateur.
Je ne comprends pas ce que vous essayez de faire avec les fuseaux horaires dans votre utilisation de ZonedDateTime
. Il semble que vous essayez de former un java.sql.Timestamp
objet. C'est la mauvaise façon de procéder pour deux raisons. Premièrement, cette classe est l'une des terribles classes de date-heure héritées du passé supprimé par java.time ; ne l'utilisent jamais. Deuxièmement, ce n'est pas la bonne façon de prendre des rendez-vous. Les rendez-vous futurs doivent être enregistrés en deux parties distinctes, (a) la date avec l'heure du jour et (b) le fuseau horaire.
Les politiciens du monde entier ont montré un penchant à modifier fréquemment le décalage des fuseaux horaires relevant de leur juridiction. Ils le font avec peu, voire pas du tout, d'avertissement. Ainsi, si vous avez réservé 15 h 45 pour le mois de janvier prochain en tant que moment, en tant que point spécifique sur la ligne du temps, l'heure du jour pour l'horloge murale de cette zone pourrait être modifiée d'ici là, 15 h 45 devenant 15 h 15 ou 16 h 45. Imaginez que votre logiciel prenne un rendez-vous pour le moment précis où était 3:45 PM antes de la zone a modifié son décalage par rapport à l'UTC. Les clients qui respectent leurs rendez-vous apparaîtront à 15 heures à l'heure de l'horloge murale actuelle, alors que votre logiciel de prise de rendez-vous les indiquera comme étant en avance (ou en retard). Pour éviter ce problème, ne pas prendre de rendez-vous à l'improviste conservez la date et l'heure du jour ( LocalDateTime
) séparé du fuseau horaire ( ZoneId
).
Ne combinez les deux (date avec heure du jour et fuseau horaire) que lorsque vous élaborez un programme pour lequel vous avez besoin de moments précis.
ZoneId z = ZoneId.of( zoneNameFromDatabase ) ;
ZonedDateTime zdt = localDateTimeFromDatabase.atZone( z ) ;
Si vous avez besoin de voir ce moment en UTC, ajustez en extrayant un Instant
objet.
Instant instant = zdt.toInstant() ;
Mais ne stockez pas non plus les ZonedDateTime
o Instant
pour l'avenir. Ne les stockez qu'après coup, lors de l'enregistrement de l'histoire. Et même dans ce cas, vous enregistrez OffsetDateTime
car, curieusement, la spécification JDBC n'exige pas le support de la fonction ZonedDateTime
o Instant
. Vous stockez ce OffsetDateTime
dans une colonne de type SQL-standard TIMESTAMP WITH TIME ZONE
("AVEC", et non "SANS" comme indiqué ci-dessus).
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ; // Record history as a moment, a specific point on the timeline.