private static ZonedDateTime parse(final DateTimeFormatter formatter, final String value, final ZoneId zoneId) {
        final TemporalAccessor temporalAccessor = formatter.parseBest(value, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
        if (temporalAccessor instanceof ZonedDateTime) {
            return ((ZonedDateTime) temporalAccessor).withZoneSameInstant(zoneId);
        }
        if (temporalAccessor instanceof LocalDateTime) {
            return ((LocalDateTime) temporalAccessor).atZone(zoneId);
        }
        return ((LocalDate) temporalAccessor).atStartOfDay(zoneId);
    }
Parse a date using a format.

@param pattern    pattern to match
@param timeZoneId if provided the pattern will append Z and the time zone will
                  be added
@param value      value to parse
@return the result
@throws IllegalArgumentException if date does not parse
stroom-legacy/stroom-legacy-model_6_1/src/main/java/stroom/legacy/model_6_1/DateUtil.java