waterml/src/main/java/ucar/nc2/ogc/erddap/util/ErddapCalendar2.java
public static double[] getTimeBaseAndFactor(String tsUnits) throws Exception {
        String errorInMethod = ErddapString2.ERROR + " in Calendar2.getTimeBaseAndFactor(" + tsUnits + "):\n";

        if (tsUnits == null) {
            throw new NullPointerException(errorInMethod + "tsUnits must be non-null.");
        }

        int sincePo = tsUnits.toLowerCase().indexOf(" since ");
        if (sincePo <= 0)
            throw new IllegalArgumentException(errorInMethod + "units string doesn't contain \" since \".");
        double factorToGetSeconds = factorToGetSeconds(tsUnits.substring(0, sincePo));
        GregorianCalendar baseGC = parseISODateTimeZulu(tsUnits.substring(sincePo + 7));
        double baseSeconds = baseGC.getTimeInMillis() / 1000.0;

        return new double[]{baseSeconds, factorToGetSeconds};
    }
public static double[] getTimeBaseAndFactor(String tsUnits) throws Exception {
        String errorInMethod = ErddapString2.ERROR + " in Calendar2.getTimeBaseAndFactor(" + tsUnits + "):\n";

        if (tsUnits == null) {
            throw new NullPointerException(errorInMethod + "tsUnits must be non-null.");
        }

        int sincePo = tsUnits.toLowerCase().indexOf(" since ");
        if (sincePo <= 0)
            throw new IllegalArgumentException(errorInMethod + "units string doesn't contain \" since \".");
        double factorToGetSeconds = factorToGetSeconds(tsUnits.substring(0, sincePo));
        GregorianCalendar baseGC = parseISODateTimeZulu(tsUnits.substring(sincePo + 7));
        double baseSeconds = baseGC.getTimeInMillis() / 1000.0;

        return new double[]{baseSeconds, factorToGetSeconds};
    }
public static double [ ] getTimeBaseAndFactor ( String tsUnits ) throws Exception { String errorInMethod = ErddapString2 . ERROR + " in Calendar2.getTimeBaseAndFactor(" + tsUnits + "):\n" ; if ( tsUnits == null ) { throw new NullPointerException ( errorInMethod + "tsUnits must be non-null." ) ; } int sincePo = tsUnits . toLowerCase ( ) . indexOf ( " since " ) ; if ( sincePo <= 0 ) throw new IllegalArgumentException ( errorInMethod + "units string doesn't contain \" since \"." ) ; double factorToGetSeconds = factorToGetSeconds ( tsUnits . substring ( 0 , sincePo ) ) ; GregorianCalendar baseGC = parseISODateTimeZulu ( tsUnits . substring ( sincePo + 7 ) ) ; double baseSeconds = baseGC . getTimeInMillis ( ) / 1000.0 ; return new double [ ] { baseSeconds , factorToGetSeconds } ; }
This converts a string "[units] since [isoDate]"
(e.g., "minutes since 1985-01-01") into
a baseSeconds (seconds since 1970-01-01) and a factor ("minutes" returns 60).
<br>So simplistically, epochSeconds = storedTime * factor + baseSeconds.
<br>Or simplistically, storedTime = (epochSeconds - baseSeconds) / factor.

<p>WARNING: don't use the equations above. Use unitsSinceToEpochSeconds or
epochSecondsToUnitsSince which correctly handle special cases.

@param tsUnits e.g., "minutes since 1985-01-01".
This may include hours, minutes, seconds, decimal, and Z or timezone offset (default=Zulu).
@return double[]{baseSeconds, factorToGetSeconds}
@throws Exception if trouble (tsUnits is null or invalid)
This converts a string [ units ] since [ isoDate ] ( e . g . minutes since 1985 - 01 - 01 ) into a baseSeconds ( seconds since 1970 - 01 - 01 ) and a factor ( minutes returns 60 ) . <br > So simplistically epochSeconds = storedTime * factor + baseSeconds . <br > Or simplistically storedTime = ( epochSeconds - baseSeconds ) / factor .