Comment gérer jodatime instant illégal en raison de la transition de décalage de fuseau horaire
je veux mettre en place joda DateTime
aujourd'hui à 2 H (voir code échantillon ci-dessous). Mais j'obtiens cette exception:
Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 2 for hourOfDay is not supported: Illegal instant due to time zone offset transition: 2011-03-27T02:52:05.239 (Europe/Prague)
at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469)
at org.joda.time.MutableDateTime.setHourOfDay(MutableDateTime.java:702)
Quelle est la bonne façon de créer un DateTime
à une heure donnée de la journée?
exemple de code:
MutableDateTime now = new MutableDateTime();
now.setHourOfDay(2);
now.setMinuteOfHour(0);
now.setSecondOfMinute(0);
now.setMillisOfSecond(0);
DateTime myDate = now.toDateTime();
Merci.
5 réponses
il semble que vous essayez de passer d'une heure locale spécifique à un DateTime
exemple et vous voulez que ce soit robuste contre l'heure d'été. Essayez ceci... (notez que je suis aux États-Unis / de L'est, donc notre date de transition était le 13 mars 11; je devais trouver la bonne date pour obtenir l'exception que vous avez obtenu aujourd'hui. Mis à jour mon code ci-dessous pour CET, qui transitions aujourd'hui.) L'idée ici est que Joda fournit LocalDateTime
pour vous permettre de raisonner sur un réglage d'horloge murale locale et si c'est légal dans votre fuseau horaire ou pas. Dans ce cas, je viens de rajouter une heure si le temps n'existe pas (votre demande de décider si c'est la bonne politique.)
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
class TestTz {
public static void main(String[] args)
{
final DateTimeZone dtz = DateTimeZone.forID("CET");
LocalDateTime ldt = new LocalDateTime(dtz)
.withYear(2011)
.withMonthOfYear(3)
.withDayOfMonth(27)
.withHourOfDay(2);
// this is just here to illustrate I'm solving the problem;
// don't need in operational code
try {
DateTime myDateBorken = ldt.toDateTime(dtz);
} catch (IllegalArgumentException iae) {
System.out.println("Sure enough, invalid instant due to time zone offset transition!");
}
if (dtz.isLocalDateTimeGap(ldt)) {
ldt = ldt.withHourOfDay(3);
}
DateTime myDate = ldt.toDateTime(dtz);
System.out.println("No problem: "+myDate);
}
}
Ce code produit:
Sure enough, invalid instant due to time zone offset transition! No problem: 2011-03-27T03:00:00.000+02:00
CET passe à DST (heure d'été) le dernier dimanche de Mars, qui se trouve être aujourd'hui. Le temps est passé de 1:59:59 à 3:00:00 – il n'y a pas 2, donc l'exception.
Vous devriez utiliser UTC au lieu de l'heure locale pour éviter ce genre de problème de fuseau horaire.
MutableDateTime now = new MutableDateTime(DateTimeZone.UTC);
je pense que beaucoup de temps, vous voulez joda réparer automatiquement pour vous. Vous ne saurez souvent pas la bonne façon de fixer une date d'intervalle parce que la taille de l'intervalle dépend de la zone et de l'année (bien sûr, il est généralement d'une heure).
un exemple de ceci est si vous analysez un timestamp qui vient d'une source que vous ne contrôlez pas; par exemple, le réseau. Si l'expéditeur de l'horodatage a des fichiers de zone périmés, cela pourrait se produire. (Si vous avez des fichiers de zone périmés, vous êtes assez bien foutue).
Voici une façon de faire, qui, est, est un peu plus compliqué. J'ai fait en sorte que ça marche dans joda 1.6 aussi bien que 2.x, puisque nous arrive d'être coincé sur 1.6 dans notre environnement.
si vous construisez une date à partir d'autres entrées comme dans votre question, vous pouvez commencer avec une date UTC ou un LocalDate
comme suggéré ci-dessus, puis adaptez ceci pour corriger automatiquement votre offset. La sauce spéciale est en DateTimeZone.convertLocalToUTC
Dangereux:
public DateTime parse(String str) {
formatter.parseDateTime(gapdate)
}
Sécurité:
public DateTime parse(String str) {
// separate date from zone; you may need to adjust the pattern,
// depending on what input formats you support
String[] parts = str.split("(?=[-+])");
String datepart = parts[0];
DateTimeZone zone = (parts.length == 2) ?
DateTimeZone.forID(parts[1]) : formatter.getZone();
// parsing in utc is safe, there are no gaps
// parsing a LocalDate would also be appropriate,
// but joda 1.6 doesn't support that
DateTime utc = formatter.withZone(DateTimeZone.UTC).parseDateTime(datepart);
// false means don't be strict, joda will nudge the result forward by the
// size of the gap. The method is somewhat confusingly named, we're
// actually going from UTC to local
long millis = zone.convertLocalToUTC(utc.getMillis(), false);
return new DateTime(millis, zone);
}
j'ai testé ceci dans les hémisphères Est et ouest ainsi que dans la zone de L'Île de Lord Howe, qui se trouve avoir une heure et demie de dst.
ce serait plutôt sympa si joda formatters soutenait un setStrict(booléen) qui leur ferait prendre soin de cela pour vous...
Si vous avez besoin d'analyser la date de chaîne de caractères:
final DateTimeZone dtz = DateTimeZone.getDefault(); //DateTimeZone.forID("Europe/Warsaw")
LocalDateTime ldt = new LocalDateTime("1946-04-14", dtz);
if (dtz.isLocalDateTimeGap(ldt)){
ldt = ldt.plusHours(1);
}
DateTime date = ldt.toDateTime();
Date date = date.toDate();
a parfaitement fonctionné pour moi. Peut-être que quelqu'un en aura besoin.
mise à Jour de jodatime 2.1 et utiliser LocalDate.parse()
:
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
LocalDate.parse(date, formatter);