Je souhaite configurer joda DateTime
à aujourd'hui à 2 heures du matin (voir l'exemple de code ci-dessous). Mais je reçois 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 l’exception ci-dessus ou de créer un DateTime
à une heure donné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.
On dirait que vous essayez de passer d'une heure locale spécifique à une instance DateTime
et que vous voulez que cela soit robuste face à l'heure d'été. Essayez ceci ... (notez que je suis aux États-Unis/dans l’Est, notre date de transition était donc le 13 mars; je devais trouver la bonne date pour obtenir l’exception que vous avez eue aujourd’hui. J'ai mis à jour le code ci-dessous pour CET, qui passe 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 de déterminer s’il est légal ou non dans votre fuseau horaire. Dans ce cas, j'ajoute simplement une heure si l'heure n'existe pas (votre application doit 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:
Bien sûr, instant invalide en raison de la transition de décalage de fuseau horaire! Pas de problème: 2011-03-27T03: 00: 00.000 + 02: 00
CET passe à l'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’ya pas 2, d’où l’exception.
Vous devez utiliser le temps UTC au lieu de l'heure locale pour éviter ce type de problème de fuseau horaire.
MutableDateTime now = new MutableDateTime(DateTimeZone.UTC);
Je pense que très souvent, vous voudrez que Joda répare cela automatiquement pour vous. Vous ne saurez souvent pas comment corriger une date de décalage, car l'ampleur de ce dernier dépend de la zone et de l'année (bien que ce soit généralement une heure).
Un exemple de ceci est si vous analysez un horodatage qui provient 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 obsolètes, cela peut se produire. (Si vous avez des fichiers de zone obsolètes, vous êtes plutôt mal foutus).
Voici un moyen de le faire, ce qui, certes, est un peu plus compliqué. Je l'ai fait fonctionner dans joda 1.6 ainsi que dans 2.x, car nous sommes bloqués sur 1.6 dans notre environnement.
Si vous construisez une date à partir d'autres entrées comme dans votre question, vous pouvez commencer par une date UTC ou une LocalDate
comme suggéré ci-dessus, puis l'adapter pour corriger automatiquement votre décalage. La sauce spéciale est dans DateTimeZone.convertLocalToUTC
Dangereux:
public DateTime parse(String str) {
formatter.parseDateTime(gapdate)
}
Sûr:
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é cela dans les hémisphères est et ouest, ainsi que dans la zone de l'île Lord Howe, où il se trouve qu'il reste une demi-heure.
Ce serait un peu gentil si les formateurs joda supportaient un setStrict (booléen) qui les ferait prendre en charge pour vous ...
Si vous devez analyser la date de la chaîne:
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();
Travaillé pour moi parfaitement. Peut-être que quelqu'un en aura besoin.
Mettez à jour jodatime 2.1 et utilisez LocalDate.parse()
:
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
LocalDate.parse(date, formatter);