All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.linuxforhealth.hl7.data.date.DateUtil Maven / Gradle / Ivy

/*
 * (C) Copyright IBM Corp. 2020, 2022
 *
 * SPDX-License-Identifier: Apache-2.0
 */
package io.github.linuxforhealth.hl7.data.date;

import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.Temporal;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.Map.Entry;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.linuxforhealth.core.config.ConverterConfiguration;

public class DateUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);

    private DateUtil() {
    }

    public static String formatToDate(String input) {
        DateTimeFormatter format = null;
        for (Entry pattern : DateFormats.getDatePatternsInstance()
                .entrySet()) {
            if (pattern.getKey().matcher(input).matches()) {
                format = pattern.getValue();
                break;
            }
        }
        try {
            LocalDate ldt = LocalDate.parse(input, DateFormats.getFormatterInstance());
            return ldt.format(format);
        } catch (DateTimeParseException e) {
            LOGGER.warn("Input value cannot be formatted to LocalDate.");
            
            return null;
        }
    }

    // Convenience method
    // Input with no zoneId, processes with the default zoneId
    // No run-time zoneId can be passed with this method,
    // So this should be used only when there is no run-time zoneId.
    public static String formatToDateTimeWithDefaultZone(String input) {
        return formatToDateTimeWithZone(input, null);
    }

    // If a DateTime from HL7 has a ZoneId in the DateTime, use it.
    // If it has no ZoneId, and the Run Time Override (RTO) is set, use that.
    // If it has no ZoneId, and not RTO, but there is a config ZoneId, use that.
    // If it has no ZoneId, and not RTO, and no config ZoneId, use the local timezone (of the server).
    // This method is often called with zoneId of null or empty ""
    public static String formatToDateTimeWithZone(String input, String zoneId) {
        String returnValue = getLocalDate(input);
        if (returnValue == null) {
            returnValue = getZonedDate(input);
        }
        if (returnValue == null) {
            returnValue = getLocalDateTimeWithZone(input, zoneId);
        }
        return returnValue;
    }

    // This method is called with zoneId of null or empty "" when the zoneIdText is not set at runtime.
    private static String getLocalDateTimeWithZone(String input, String zoneIdText) {
        try {
            LocalDateTime ldt = LocalDateTime.parse(input, DateFormats.getFormatterInstance());
            // Attempt to recognize the input zoneIdText, if it is not null
            ZoneId zone = zoneIdText != null ? getZoneIdFromText(zoneIdText) : null;
            // Warn if we've got a non-null non-empty string that we can't convert
            if (zoneIdText != null && (!zoneIdText.isEmpty() && zone == null)){
                LOGGER.warn("Input zoneId not recognized.  Using default Zone.");
                
            }
            // If there is no valid input zoneId, use the config.properties zoneId
            if (zone == null) {
                zone = ConverterConfiguration.getInstance().getZoneId();
            }
            // If there is no Configured ZoneId, use the default of the server.
            if (zone == null) {
                zone = getZoneIdFromText(TimeZone.getDefault().getID());
            }
            // One of the above should have provided a zone.
            if (zone != null) {
                return ldt.atZone(zone).format(DateFormats.FHIR_ZONE_DATE_TIME_FORMAT);
            } else {
                LOGGER.warn("No default zone set, cannot convert LocalDateTime to ZonedDateTime");
                
                return null;
            }
        } catch (DateTimeParseException e) {
            LOGGER.warn("Date parsing failure for value.");
            
            return null;
        }
    }

    private static ZoneId getZoneIdFromText(String zoneIdText){
        try {
            return ZoneId.of(zoneIdText);
          } catch (DateTimeException e) {
            LOGGER.warn("Cannot create ZoneId");
            
            // Leave zoneId as it was.
          }
        return null;
    }

    // Matches an input string to a local date using the known patterns
    private static String getLocalDate(String input) {
        DateTimeFormatter format = null;
        for (Entry pattern : DateFormats
                .getDatePatternsWithoutTimeInstance().entrySet()) {
            if (pattern.getKey().matcher(input).matches()) {
                format = pattern.getValue();
                break;
            }
        }
        if (format != null) {
            try {
                LocalDate ldt = LocalDate.parse(input, DateFormats.getFormatterInstance());
                return ldt.atStartOfDay().format(format);
            } catch (DateTimeParseException e) {
                LOGGER.warn("Input value cannot be formatted to LocalDate");
                
                return null;
            }
        }
        return null;
    }

    private static String getZonedDate(String input) {
        DateTimeFormatter format = null;
        for (Entry pattern : DateFormats.getDatePatternsWithZoneInstance()
                .entrySet()) {
            if (pattern.getKey().matcher(input).matches()) {
                format = pattern.getValue();
                break;
            }
        }
        if (format != null) {
            try {
                ZonedDateTime zdt = ZonedDateTime.parse(input, DateFormats.getFormatterInstance());
                return zdt.format(format);
            } catch (DateTimeParseException e) {
                LOGGER.warn("Input value cannot be parsed to ZonedDateTime");
                
                return null;
            }
        }
        return null;
    }

    public static Temporal getTemporal(String dateString) {
        Map warnings = new HashMap<>();
        if (dateString == null) {
            return null;
        }
        Temporal temporal = null;
        try {
            temporal = Instant.parse(dateString);
            
        } catch (DateTimeParseException e) {
            warnings.put("Input value cannot be parsed to  instant " + dateString, e);
        }
        if (temporal == null) {
            try {
                temporal = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_ZONED_DATE_TIME);
                
            } catch (DateTimeParseException e) {
                warnings.put("Input value cannot be parsed to ZonedDateTime " + dateString, e);
            }
        }
        if (temporal == null) {
            try {
                temporal = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                
            } catch (DateTimeParseException e) {
                warnings.put("Input value cannot be parsed to LocalDateTime " + dateString, e);
            }
        }
        if (temporal == null) {
            try {
                temporal = LocalDate.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE);
                
            } catch (DateTimeParseException e) {
                warnings.put("Input value cannot be parsed to LocalDate " + dateString, e);
            }
        }
        if (temporal == null && !warnings.isEmpty()) {
            LOGGER.warn("Attempt to parse input value to temporal failed.");
            
            for (Entry entry : warnings.entrySet()) {
                
            }
        }
        return temporal;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy