001/* 002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.tribuo.data.columnar.extractors; 018 019import com.oracle.labs.mlrg.olcut.config.Config; 020import com.oracle.labs.mlrg.olcut.provenance.ConfiguredObjectProvenance; 021import com.oracle.labs.mlrg.olcut.provenance.impl.ConfiguredObjectProvenanceImpl; 022 023import java.time.LocalDate; 024import java.time.format.DateTimeFormatter; 025import java.time.format.DateTimeParseException; 026import java.util.Optional; 027import java.util.logging.Level; 028import java.util.logging.Logger; 029 030/** 031 * Extracts the field value and translates it to a {@link LocalDate} based on the specified {@link DateTimeFormatter}. 032 * <p> 033 * Returns an empty optional if the date failed to parse. 034 */ 035public class DateExtractor extends SimpleFieldExtractor<LocalDate> { 036 private static final Logger logger = Logger.getLogger(DateExtractor.class.getName()); 037 038 @Config(mandatory = true, description = "The expected date format.") 039 private String dateFormat; 040 private DateTimeFormatter formatter; 041 042 /** 043 * for olcut 044 */ 045 private DateExtractor() {} 046 047 /** 048 * Constructs a date extractor that emits a LocalDate by applying the supplied format to the specified field. 049 * @param fieldName The field to read. 050 * @param metadataName The metadata field to write. 051 * @param dateFormat The date format (supplied to {@link DateTimeFormatter}. 052 */ 053 public DateExtractor(String fieldName, String metadataName, String dateFormat) { 054 super(fieldName, metadataName); 055 this.dateFormat = dateFormat; 056 postConfig(); 057 } 058 059 /** 060 * Constructs a date extractor that emits a LocalDate by applying the supplied format to the specified field. 061 * <p> 062 * Deprecated as it does not allow recovery of the formatter pattern for the provenance. 063 * @param fieldName The field to read. 064 * @param metadataName The metadata field to write. 065 * @param formatter The date format (supplied to {@link DateTimeFormatter}. 066 */ 067 @Deprecated 068 public DateExtractor(String fieldName, String metadataName, DateTimeFormatter formatter) { 069 super(fieldName, metadataName); 070 this.formatter = formatter; 071 } 072 073 /** 074 * Used by the OLCUT configuration system, and should not be called by external code. 075 */ 076 @Override 077 public void postConfig() { 078 if (dateFormat != null) { 079 formatter = DateTimeFormatter.ofPattern(dateFormat); 080 } else { 081 formatter = DateTimeFormatter.BASIC_ISO_DATE; 082 } 083 if (metadataName == null || metadataName.isEmpty()) { 084 metadataName = fieldName; 085 } 086 } 087 088 @Override 089 public Class<LocalDate> getValueType() { 090 return LocalDate.class; 091 } 092 093 @Override 094 protected Optional<LocalDate> extractField(String s) { 095 try { 096 return Optional.of(LocalDate.parse(s, formatter)); 097 } catch (DateTimeParseException e) { 098 logger.log(Level.WARNING, e.getParsedString()); 099 logger.log(Level.WARNING, String.format("Unable to parse date %s with formatter %s", s, formatter.toString())); 100 return Optional.empty(); 101 } 102 } 103 104 @Override 105 public String toString() { 106 return "DateExtractor(fieldName=" + fieldName + ", metadataName=" + metadataName + ", dateFormat=" + formatter.toString() + ")"; 107 } 108 109 @Override 110 public ConfiguredObjectProvenance getProvenance() { 111 return new ConfiguredObjectProvenanceImpl(this, "DateExtractor"); 112 } 113}