C'est ubansi en charge du deuxième jour du calendrier de l'Avent Java! Vers l'année dernière Code Java diabolique combattu.
Les fichiers de vidage de différentes bases de données sont placés dans Bashibashi BigQuery!
Eh, la date n'est pas analysée par BigQuery ...? Puis-je modifier la sortie car d'autres systèmes sont en cours d'exécution? Y a-t-il un décalage horaire? Eh, ajouter DB?
・ ・ ・
Pour ceux qui rencontrent de telles choses
(Plutôt, j'ai rencontré un tel œil)
Créons un processus pour convertir toutes les chaînes de date en LocalDateTime
dans Java8.
Présentation de la classe du temps cool! ZonedDateTime Une classe qui gère ** les dates avec l'heure ** pour chaque fuseau horaire. Il considère également l'heure d'été.
OffsetDateTime Une classe qui gère ** les dates avec l'heure ** pour chaque décalage horaire. S'il existe une spécification de décalage horaire au lieu d'une spécification de fuseau horaire, c'est le tour.
LocalDateTime Inutile de dire que ce cours traite du ** temps sans décalage horaire **. Cette fois, nous allons nous convertir à cette classe.
LocalDate
Une classe qui gère ** date ** sans décalage horaire.
Si aucune heure n'est spécifiée, cette classe sera utilisée pour l'analyse.
Vous pouvez le convertir en LocalDateTime à minuit avec LocalDate # atStartOfDay ()
.
Timestamp Utilisé pour la conversion depuis Unixtime.
Oui, commençons l'explication. En tant que procédure, la conversion est tentée dans l'ordre décroissant de la quantité d'informations en tant que résultat de l'analyse. Ensuite, lorsque la conversion est terminée, le résultat est renvoyé. ** Seulement lorsque toutes les analyses échouent ** Je lancerai toutes les erreurs.
Créez une classe abstraite pour l'analyser et en hériter.
TimeParser.java
public abstract class TimeParser {
/**
* fails info
*/
protected List<String> failsMessages = new ArrayList<>();
/**
* This function forcibly converts a string to a date.
*<p>
* If the return value is null, please throw an {@code DateTimeParseException}.
* </p>
* @param input
* @return LocalDateTime instance or {@code null}
*/
public abstract LocalDateTime parse(String input);
protected void addExceptionMessage(Exception e) {
failsMessages.add(e.getMessage() + " ("+this.getClass().getSimpleName()+")");
}
public List<String> getExceptionInfo(){
return failsMessages;
};
}
Il comporte une partie analyse et une partie acquisition de logs. Pour le moment, je garde un journal afin de voir ce qui s'est passé si tout a échoué.
LocalDateParser.java
public class LocalDateParser extends TimeParser {
//Définissez le format à une extrémité
private final static List<DateTimeFormatter> FORMATS = new ArrayList<DateTimeFormatter>() {
{
add(DateTimeFormatter.ISO_LOCAL_DATE);
add(DateTimeFormatter.BASIC_ISO_DATE);
add(DateTimeFormatter.ISO_DATE);
add(DateTimeFormatter.ofPattern("yy-MM-dd"));
add(DateTimeFormatter.ofPattern("yy-M-d"));
add(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
add(DateTimeFormatter.ofPattern("yyyy/M/d"));
add(DateTimeFormatter.ofPattern("aaaa année M mois j jour"));
}
};
@Override
public LocalDateTime parse(String input) {
failsMessages.clear();
//Essayez l'analyse par défaut
try {
return LocalDate.parse(input).atStartOfDay();
} catch (DateTimeParseException e) {
addExceptionMessage(e);
}
//Analyser au format spécifié
for (DateTimeFormatter formatter : FORMATS) {
try {
return LocalDate.parse(input, formatter).atStartOfDay();
} catch (DateTimeParseException e) {
//Enregistrez le journal des échecs dans la liste
addExceptionMessage(e);
}
}
return null;
}
}
Si une DateTimeParseException
se produit, stockez simplement le journal et
Je vais tout presser.
La raison pour laquelle l'enregistreur ne génère pas de sortie lorsqu'une exception se produit est qu'il est généré même s'il n'y a pas de problème de traitement.
Créez une classe qui hérite de TimeParser comme celle-ci dans d'autres classes de dates.
DateTimeParser.java
public class DateTimeParser {
//Liste de rétention des erreurs
private List<String> errors = new ArrayList<>();
//Créer une classe d'analyse
private final static List<TimeParser> PARSERS = new ArrayList<TimeParser>() {
{
//Analyser par ordre décroissant de quantité d'informations
add(new ZonedDateTimeParser());
add(new OffsetDateTimeParser());
add(new LocalDateTimeParser());
add(new LocalDateParser());
add(new TimestampParser());
}
};
public LocalDateTime parse(String input) {
errors.clear();
LocalDateTime result = null;
for (TimeParser parser : PARSERS) {
result = parser.parse(input);
//Renvoie le résultat lorsqu'il réussit
if (result != null) {
return result;
}
errors.addAll(parser.getExceptionInfo());
}
throw new DateTimeParseException("L'analyse a échoué.(\"" + input + "\")", input, 0);
//Il n'y a pas de retour!
}
public List<String> getErrors(){
return errors;
}
}
Il contient une liste de classes et de boucles d'analyse. Si l'analyse réussit, une instance de LocalDateTime sera renvoyée, donc Renvoie le résultat s'il n'est pas «nul».
De plus, l'exception d'analyse qui s'est produite au milieu peut être récupérée après analyse avec getErrors ()
.
(Ce n'est pas thread-safe ...)
Et seulement si cela échoue, il lève une exception à la fin. C'est une méthode bizarre sans "return".
return
, Eclipse se mettra en colère parce que c'est une erreur.DateTimeParserTest.java
@Test
public void testDateFormat() {
//Tester si cette date peut être convertie
List<String> dates = new ArrayList<String>() {
{
add("2017-12-02");
add("17-12-02");
add("17-12-2");
add("20171202");
add("2017/12/02");
add("2017/12/2");
add("2 décembre 2017");
}
};
for (String date : dates) {
LocalDateTime time = dtp.parse(date);
assertEquals("2017-12-02T00:00:00", time.format(formater));
}
}
C'est un test difficile, mais si vous analysez toutes les dates comme ça, Tout pourrait être analysé comme "2017-12-02T 00:00:00". Vous devriez pouvoir convertir n'importe quelle date en ajoutant des formats à la ArrayList des différentes classes d'analyseur.
Tu l'as fait!
À propos, l'exemple de code utilisé cette fois est publié sur GitHub. https://github.com/ubansi/DateTimeParser
Recommended Posts