/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.elasticsearch.ingest.common; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.ingest.AbstractProcessor; import org.elasticsearch.ingest.ConfigurationUtils; import org.elasticsearch.ingest.IngestDocument; import org.elasticsearch.ingest.Processor; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.format.ISODateTimeFormat; import java.util.ArrayList; import java.util.IllformedLocaleException; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; public final class DateProcessor extends AbstractProcessor { public static final String TYPE = "date"; static final String DEFAULT_TARGET_FIELD = "@timestamp"; private final DateTimeZone timezone; private final Locale locale; private final String field; private final String targetField; private final List<String> formats; private final List<Function<String, DateTime>> dateParsers; DateProcessor(String tag, DateTimeZone timezone, Locale locale, String field, List<String> formats, String targetField) { super(tag); this.timezone = timezone; this.locale = locale; this.field = field; this.targetField = targetField; this.formats = formats; this.dateParsers = new ArrayList<>(this.formats.size()); for (String format : formats) { DateFormat dateFormat = DateFormat.fromString(format); dateParsers.add(dateFormat.getFunction(format, timezone, locale)); } } @Override public void execute(IngestDocument ingestDocument) { String value = ingestDocument.getFieldValue(field, String.class); DateTime dateTime = null; Exception lastException = null; for (Function<String, DateTime> dateParser : dateParsers) { try { dateTime = dateParser.apply(value); } catch (Exception e) { //try the next parser and keep track of the exceptions lastException = ExceptionsHelper.useOrSuppress(lastException, e); } } if (dateTime == null) { throw new IllegalArgumentException("unable to parse date [" + value + "]", lastException); } ingestDocument.setFieldValue(targetField, ISODateTimeFormat.dateTime().print(dateTime)); } @Override public String getType() { return TYPE; } DateTimeZone getTimezone() { return timezone; } Locale getLocale() { return locale; } String getField() { return field; } String getTargetField() { return targetField; } List<String> getFormats() { return formats; } public static final class Factory implements Processor.Factory { @SuppressWarnings("unchecked") public DateProcessor create(Map<String, Processor.Factory> registry, String processorTag, Map<String, Object> config) throws Exception { String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field"); String targetField = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "target_field", DEFAULT_TARGET_FIELD); String timezoneString = ConfigurationUtils.readOptionalStringProperty(TYPE, processorTag, config, "timezone"); DateTimeZone timezone = timezoneString == null ? DateTimeZone.UTC : DateTimeZone.forID(timezoneString); String localeString = ConfigurationUtils.readOptionalStringProperty(TYPE, processorTag, config, "locale"); Locale locale = Locale.ENGLISH; if (localeString != null) { try { locale = (new Locale.Builder()).setLanguageTag(localeString).build(); } catch (IllformedLocaleException e) { throw new IllegalArgumentException("Invalid language tag specified: " + localeString); } } List<String> formats = ConfigurationUtils.readList(TYPE, processorTag, config, "formats"); return new DateProcessor(processorTag, timezone, locale, field, formats, targetField); } } }