class MDateAndTime {

    public static StringType parseDateOrTime(String st, long[] dt) {
        assert dt.length >= MAX_INDEX;

        st = st.trim();
        String year = "0";
        String month = "0";
        String day = "0";
        String hour = "0";
        String minute = "0";
        String seconds = "0";

        Matcher matcher;
        if((matcher = DATE_PATTERN.matcher(st)).matches()) {
            StringType type = StringType.DATE_ST;
            year = matcher.group(DATE_YEAR_GROUP);
            month = matcher.group(DATE_MONTH_GROUP);
            day = matcher.group(DATE_DAY_GROUP);
            if(matcher.group(TIME_GROUP) != null) {
                type = StringType.DATETIME_ST;
                hour = matcher.group(TIME_HOUR_GROUP);
                minute = matcher.group(TIME_MINUTE_GROUP);
                seconds = matcher.group(TIME_SECOND_GROUP);
            }
            if(stringsToLongs(dt, true, year, month, day, hour, minute, seconds) &&
               isValidDateTime_Zeros(dt)) {
                return type;
            }
            return (type == StringType.DATETIME_ST) ? StringType.INVALID_DATETIME_ST : StringType.INVALID_DATE_ST;
        }
        else if((matcher = TIME_WITH_DAY_PATTERN.matcher(st)).matches())
        {   
            day = matcher.group(MDateAndTime.TIME_WITH_DAY_DAY_GROUP);
            hour = matcher.group(MDateAndTime.TIME_WITH_DAY_HOUR_GROUP);
            minute = matcher.group(MDateAndTime.TIME_WITH_DAY_MIN_GROUP);
            seconds = matcher.group(MDateAndTime.TIME_WITH_DAY_SEC_GROUP);
            if(stringsToLongs(dt, false, year, month, day, hour, minute, seconds) &&
               isValidHrMinSec(dt, false, false)) {
                // adjust DAY to HOUR 
                int sign = 1;
                if(dt[DAY_INDEX] < 0) {
                    dt[DAY_INDEX] *= (sign = -1);
                }
                dt[HOUR_INDEX] = sign * (dt[HOUR_INDEX] += dt[DAY_INDEX] * 24);
                dt[DAY_INDEX] = 0;
                return StringType.TIME_ST;
            }
            return StringType.INVALID_TIME_ST;
        }
        else if((matcher = TIME_WITHOUT_DAY_PATTERN.matcher(st)).matches())
        {
            hour = matcher.group(MDateAndTime.TIME_WITHOUT_DAY_HOUR_GROUP);
            minute = matcher.group(MDateAndTime.TIME_WITHOUT_DAY_MIN_GROUP);
            seconds = matcher.group(MDateAndTime.TIME_WITHOUT_DAY_SEC_GROUP);
            if(stringsToLongs(dt, false, year, month, day, hour, minute, seconds) &&
               isValidHrMinSec(dt, false, false)) {
                return StringType.TIME_ST;
            }
            return StringType.INVALID_TIME_ST;
        }
        else // last attempt, split by any DELIM and look for 3 or 6 parts
        {
            String[] parts = st.split("\\s++");
            if(parts.length == 2) {
                String[] dTok = parts[0].split(DELIM);
                String[] tTok = parts[1].split(DELIM);
                if((dTok.length == 3) && (tTok.length == 3)) {
                    if(stringsToLongs(dt, true, dTok[0], dTok[1], dTok[2], tTok[0], tTok[1], tTok[2]) &&
                       isValidDateTime_Zeros(dt)) {
                        return StringType.DATETIME_ST;
                    }
                    return StringType.INVALID_DATETIME_ST;
                }
            } else if(parts.length == 1) {
                String[] dTok = parts[0].split(DELIM);
                if(dTok.length == 3) {
                    if(stringsToLongs(dt, true, dTok[0], dTok[1], dTok[2]) &&
                       isValidDateTime_Zeros(dt)) {
                        return StringType.DATE_ST;
                    }
                    return StringType.INVALID_DATE_ST;
                }
            }
        }
        return StringType.UNPARSABLE;
    }

}