[JAVA] Je vais absolument convertir la chaîne de temps!

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.

D'accord, je vais analyser le big data!

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.

Classe utilisée pour l'analyse

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.

couler

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.

Constitution

Créez une classe abstraite pour l'analyser et en hériter.

クラス図

code

Classe abstraite de classe d'analyse

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é.

Implémentation de la classe d'analyse

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.

La classe qui sera la façade de l'analyse

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".

tester

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

Je vais absolument convertir la chaîne de temps!
J'ai lu la source de String
J'ai essayé de toucher Docker pour la première fois
[Rails] J'ai essayé d'utiliser la méthode button_to pour la première fois
Réglez la date et l'heure à partir de la chaîne de caractères avec POI
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java