/** * Copyright 2010 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package org.drools.time; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.drools.RuntimeDroolsException; /** * A helper class with utility methods for * time related operations. * * @author etirelli */ public class TimeUtils { // Simple syntax private static final Pattern SIMPLE = Pattern.compile( "([+-])?((\\d+)[Dd])?\\s*((\\d+)[Hh])?\\s*((\\d+)[Mm])?\\s*((\\d+)[Ss])?\\s*((\\d+)([Mm][Ss])?)?" ); private static final int SIM_SGN = 1; private static final int SIM_DAY = 3; private static final int SIM_HOU = 5; private static final int SIM_MIN = 7; private static final int SIM_SEC = 9; private static final int SIM_MS = 11; // ISO 8601 compliant // private static final Pattern ISO8601 = Pattern.compile( "(P((\\d+)[Yy])?((\\d+)[Mm])?((\\d+)[Dd])?)?(T((\\d+)[Hh])?((\\d+)[Mm])?((\\d+)[Ss])?((\\d+)([Mm][Ss])?)?)?" ); private static final long SEC_MS = 1000; private static final long MIN_MS = 60 * SEC_MS; private static final long HOU_MS = 60 * MIN_MS; private static final long DAY_MS = 24 * HOU_MS; // private static final long MON_MS = 30 * DAY_MS; // private static final long YEA_MS = 365 * DAY_MS; /** * This method calculates the transitive closure of the given adjacency matrix * in order to find the temporal distance between each event represented in the * adjacency matrix. * * For more information on the calculation of the temporal distance, please refer * to the paper: * * "Discarding Unused Temporal Information in a Production System", by Dan Teodosiu * and Gunter Pollak. * * This method also uses an adaptation of the Floyd-Warshall algorithm to calculate * the transitive closure of the interval matrix. More information can be found here: * * http://en.wikipedia.org/wiki/Floyd-Warshall_algorithm * * The adaptation of the algorithm follows the definition of the path addition and * path intersection operations as defined in the paper previously mentioned. The * algorithm runs in O(n^3). * * @param constraintMatrix the starting adjacency matrix * * @return the resulting temporal distance matrix */ public static Interval[][] calculateTemporalDistance( Interval[][] constraintMatrix ) { Interval[][] result = new Interval[constraintMatrix.length][]; for( int i = 0; i < result.length; i++ ) { result[i] = new Interval[constraintMatrix[i].length]; for( int j = 0; j < result[i].length; j++ ) { result[i][j] = constraintMatrix[i][j].clone(); } } for( int k = 0; k < result.length; k++ ) { for( int i = 0; i < result.length; i++ ) { for( int j = 0; j < result.length; j++ ) { Interval interval = result[i][k].clone(); interval.add( result[k][j] ); result[i][j].intersect( interval); } } } return result; } /** * Parses the given time String and returns the corresponding time * in milliseconds * * @param time * @return * * @throws NullPointerException if time is null */ public static long parseTimeString( String time ) { String trimmed = time.trim(); long result = 0; if( trimmed.length() > 0 ) { Matcher mat = SIMPLE.matcher( trimmed ); if ( mat.matches() ) { int days = (mat.group( SIM_DAY ) != null) ? Integer.parseInt( mat.group( SIM_DAY ) ) : 0; int hours = (mat.group( SIM_HOU ) != null) ? Integer.parseInt( mat.group( SIM_HOU ) ) : 0; int min = (mat.group( SIM_MIN ) != null) ? Integer.parseInt( mat.group( SIM_MIN ) ) : 0; int sec = (mat.group( SIM_SEC ) != null) ? Integer.parseInt( mat.group( SIM_SEC ) ) : 0; int ms = (mat.group( SIM_MS ) != null) ? Integer.parseInt( mat.group( SIM_MS ) ) : 0; long r = days * DAY_MS + hours * HOU_MS + min * MIN_MS + sec * SEC_MS + ms; if( mat.group(SIM_SGN) != null && mat.group( SIM_SGN ).equals( "-" ) ) { r = -r; } result = r; } else if( "*".equals( trimmed ) || "+*".equals( trimmed ) ) { // positive infinity result = Long.MAX_VALUE; } else if( "-*".equals( trimmed ) ) { // negative infinity result = Long.MIN_VALUE; } else { throw new RuntimeDroolsException( "Error parsing time string: [ " + time + " ]" ); } } return result; } }