Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: desmoj/TimeConverter.java


1   package desmoj;
2   
3   import java.util.Date;
4   import java.util.Locale;
5   import java.text.SimpleDateFormat;
6   import java.text.ParseException;
7   
8   /** TimeConverter is a class used by Experiment to convert sim time values
9    *  to true time values and vice versa. A true time value is a point in "real"
10   *  time specified as a String consisting of a date and a time,
11   *  for example "26.3.2001 13:25". In order to map the sim time values to
12   *  true time values a reference time and a time unit are needed.
13   *  The class <code>TimeConverter</code> implements the interface
14   *  {@link desmoj.Units Units} to easily use the time units and conversion factors
15   *  defined there.
16   *  <p>
17   *  Every experiment has its own time converter and provides methods for
18   *  time conversion. The <code>TimeConverter</code> class is not intended for
19   *  direct use in model components because handling of (simulation) time should
20   *  be done in experiments only.
21   *  Instead, if a model component needs to convert true time values to sim time
22   *  or vice versa it has to call the appropriate methods of the class
23   *  <code>Experiment</code>.
24   *
25   *  @author Ruth Meyer
26   *
27   *  @version DESMO-J,  Ver. 1.5 copyright (c) 2001 licensed under GNU GPL
28   *
29   *  @see desmoj.Experiment#toSimTime
30   *  @see desmoj.Experiment#toTrueTime
31   */
32  class TimeConverter implements Units {
33  
34    /** The default output format pattern for true time values as a constant.
35     *  Specified according to the time format syntax used in the
36     *  <code>java.text.SimpleDateFormat</code> class.
37     */
38    static final String DEFAULT_PATTERN = "dd.MM.yyyy HH:mm:ss:SSS";
39  
40    /** The default date used for true time values is <tt>1.1.1970</tt>.
41     */
42    static final String DEFAULT_DATE = "1.1.1970";
43  
44    /** The default time used for true time values is <tt>0:00:00</tt>.
45     */
46    static final String DEFAULT_TIME = "00:00:00";
47  
48    /** The default time unit is <code>Units.MIN</tt>.
49     */
50    static final int DEFAULT_UNIT = Units.MIN;
51  
52    /** The interval between reference time (= start time of simulation)
53     *  and default time of class <code>java.util.Date</code> (= 1.1.1970 0:00:00)
54     *  in milliseconds.
55     */
56    private long offset;
57  
58    /** The reference time unit as a constant defined in interface
59     *  <code>Units</code>.
60     */
61    private int unit;
62  
63    /** The output formatter for true time values. Uses the default pattern
64     *  if no other pattern is specified via call of the
65     *  {@link #setTimeFormat(String) setTimeFormat} method.
66     */
67    private SimpleDateFormat outFormat;
68  
69    /** The start time of the simulation as double (sim time).
70     *  Default is 0.0.
71     */
72    private double startSimTime;
73  
74  
75    /** Default constructor for a time converter using the defined constants
76     *  as default values for reference time (1.1.1970 0:00:00) and reference
77     *  time unit (minutes).
78     *  @throws java.text.ParseException Is never thrown because the default
79     *  values for reference time have a valid format.
80     */
81    public TimeConverter()
82      throws ParseException
83    {
84      this(DEFAULT_DATE + " " + DEFAULT_TIME, DEFAULT_UNIT);
85    }
86    /** Constructs a time converter with given reference time and reference
87     *  unit. The reference time String should follow the format:
88     *  <tt>&lt;date&gt;&lt;blank&gt;&lt;time&gt;<tt> with <tt>&lt;date&gt; = [d]d.[M]M.[yy]yy</tt> and
89     *  <tt>&lt;time&gt; = [H]H[:[m]m[:[s]s[:[S][S]S]]]</tt>
90     *  @param referenceTime String : the reference time as a String
91     *  @param referenceUnit int : the reference time unit as a constant defined
92     *  in the {@link desmoj.Units Units} interface
93     *  @throws java.text.ParseException if an error occurred while parsing
94     *  the reference time
95     */
96    public TimeConverter(String referenceTime, int referenceUnit)
97      throws ParseException
98    {
99      // initialize instance variables
100     this.unit = referenceUnit;
101     this.outFormat = new SimpleDateFormat(DEFAULT_PATTERN, Locale.GERMANY);
102     this.startSimTime = 0.0;
103     // parse parameter referenceTime
104     String completeRefTime = checkRefTime(referenceTime);
105     String pattern = constructPattern(completeRefTime);
106     SimpleDateFormat inFormat = new SimpleDateFormat(pattern, Locale.GERMANY);
107     Date ref = inFormat.parse(completeRefTime);
108     // calculate offset = millisecs since 1.1.1970 0:00:00
109     this.offset = ref.getTime();
110   }
111   /** Checks if the given reference time is complete. A complete true time
112    *  value consists of &lt;date&gt;&lt;blank&gt;&lt;time&gt; with
113    *  &lt;date&gt; = [d]d.[M]M.[yy]yy and
114    *  &lt;time&gt; = [H]H[:[m]m[:[s]s[:[S][S]S]]].
115    *  If date or time is missing, the default values are used instead.
116    */
117   private String checkRefTime(String refTime) {
118     StringBuffer completeTime = new StringBuffer(17);
119     if (refTime == null) {
120       // neither date nor time --> use default values for both
121       completeTime.append(DEFAULT_DATE);
122       completeTime.append(" ");
123       completeTime.append(DEFAULT_TIME);
124     }
125     else {
126        int spacePos = refTime.indexOf(" ");
127        if (spacePos < 0) {
128          int pointPos = refTime.indexOf(".");
129          if (pointPos < 0) {
130            // apparently time only --> use default date
131           completeTime.append(DEFAULT_DATE);
132           completeTime.append(" ");
133           completeTime.append(refTime);
134          }
135         else {
136           // apparently date only --> use default time
137           completeTime.append(refTime);
138           completeTime.append(" ");
139           completeTime.append(DEFAULT_TIME);
140         }
141        }
142       else {
143         // both date and time exist --> use given refTime
144         completeTime.append(refTime);
145       }
146     }
147     return completeTime.toString();
148   }
149   ///////////////////// helper methods /////////////////////////////////////
150 
151   /** Constructs a pattern to be used for parsing the given timeString.
152    *  This private helper method is called in any of the above methods
153    *  when a true time parameter has to be parsed.
154    *  The following assumptions are made:
155    *  <ol>
156    *  <li>timeString consists of a date and a time separated by a blank
157    *  (<tt>&lt;date&gt; &lt;time&gt;</tt>)</li>
158    *  <li>&lt;date&gt; has the format <tt>[d]d.[M]M.[yy]yy</tt></li>
159    *  <li>&lt;time&gt; has the format <tt>[H]H[:[m]m[:[s]s[:[S][S]S]]]</tt>
160    *  </ol>
161    *  Because the <code>SimpleDateFormat</code> class can use "minimal"
162    *  patterns (for example: the pattern "d.M.yy" is okay for all dates
163    *  consisting of 1 or 2 day digits, 1 or 2 month digits, and 2 or 4
164    *  year digits, separated by dots) the date format is no problem.
165    *  But the time has to be checked on the number of elements (hours,
166    *  minutes, seconds, milliseconds) used in order to construct the
167    *  appropriate pattern.
168    */
169   private String constructPattern(String timeString) {
170     StringBuffer pattern = new StringBuffer(14);
171     pattern.append("d.M.yy ");
172     int spacePos = timeString.indexOf(" ");
173     if (spacePos < 0) {
174       // no time specified --> return pattern "as is"
175       return pattern.toString();
176     }
177      // determine number of colons (:) in order to get number of time elements
178      int numberOfDelimiters = 0;
179      int pos = timeString.indexOf (":", spacePos);
180      while (pos >= 0) {
181        pos = timeString.indexOf (":", pos+1);
182        numberOfDelimiters++;
183      }
184      // the time format depends on the number of elements
185     // for each element use the minimal form
186     switch (numberOfDelimiters) {
187       case 3: pattern.insert(7, ":S");
188       case 2: pattern.insert(7, ":s");
189       case 1: pattern.insert(7, ":m");
190       case 0: pattern.insert(7, "H");
191     }
192     return pattern.toString();
193   }
194   /** Returns the reference time as as String formatted as defined in the
195    *  default output format pattern. A different format may be specified
196    *  via call of the <code>setTimeFormat(String)</code> method.
197    *  @return String : the reference time which is the true time of the
198    *  simulation start. It is mapped to simulation time 0.0 if no other
199    *  simulation start time is specified.
200    */
201   public String getReferenceTime() {
202     return this.outFormat.format(new Date(this.offset));
203   }
204   /** Returns the reference time unit as a constant defined in the <code>
205    *  Units</code> interface.
206    *  @return the reference unit specifying what is meant by the simulation
207    *  time step 1.0
208    */
209   public int getReferenceUnit() {
210     return this.unit;
211   }
212   /** Resets the time format used to format true time values to the default
213    *  pattern.
214    *  @see #DEFAULT_PATTERN
215    */
216   public void resetTimeFormat() {
217     this.outFormat.applyPattern(DEFAULT_PATTERN);
218   }
219   /** Sets the start time of the simulation to <code>initTime</code>.
220    *  This method must be called if a start time other than 0.0 is used.
221    *  @param initTime double the simulation start time as double (value of
222    *  <code>SimTime</code>)
223    */
224   public void setStartSimTime(double initTime) {
225     this.startSimTime = initTime;
226   }
227   /** Sets the time format used to format true time values. Initially, the
228    *  default pattern is used for formatting.
229    *  @param pattern String : the time format to be used for formatting true
230    *  time values. It must follow the time format syntax given in class
231    *  {@link java.text.SimpleDateFormat SimpleDateFormat}.
232    */
233   public void setTimeFormat(String pattern) {
234     this.outFormat.applyPattern(pattern);
235   }
236   /** Converts the given duration with the given time unit into a sim time
237    *  value. The duration is interpreted as the interval between sim time
238    *  0.0 and the calculated sim time value.
239    *  @param duration double : the duration value to be converted
240    *  @param unit int : the time unit for the duration as a constant defined
241    *  in the {@link desmoj.Units Units} interface
242    *  @return SimTime the sim time representing the given duration
243    */
244   public SimTime toSimTime(double duration, int unit) {
245     // transform duration in sim time
246     // - because SimTime doesn't distinguish between points in time and
247     //   durations of time, a duration is interpreted as the interval between
248     //   sim time 0.0 and the corresponding duration sim time.
249     // - the given duration is in the given unit -> just has to be converted
250     //   to reference unit
251     double simDuration = duration * unitFactors[unit] / unitFactors[this.unit];
252     return new SimTime(simDuration);
253   }
254   /** Converts the given true time value to the corresponding sim time value.
255    *  @param trueTime String : the true time value to be converted as a String
256    *  following the time format syntax of class <code>SimpleDateFormat</code>.
257    *  @return SimTime : the sim time representing the given true time
258    *  @throws java.text.ParseException If an error occurred while parsing
259    *  the given true time String
260    *  @see java.text.SimpleDateFormat
261    */
262   public SimTime toSimTime(String trueTime)
263      throws ParseException
264   {
265     // transform true time to sim time
266     String pattern = constructPattern(trueTime);
267     SimpleDateFormat inFormat = new SimpleDateFormat(pattern, Locale.GERMANY);
268     Date trueDate = inFormat.parse(trueTime);
269     // for this, subtract offset from trueDate (both are in milliseconds),
270     // convert into reference unit and then add startSimTime (is in ref unit)
271     return new SimTime(((double)(trueDate.getTime()-this.offset))
272                   * unitFactors[MS] / unitFactors[this.unit]
273                  + this.startSimTime);
274   }
275   /** Converts the given sim time value to the corresponding true time value.
276    *  @param simTime SimTime : the sim time value to be converted
277    *  @return String : the true time representing the given sim time as a
278    *  String formatted according to the currently used time format. Initially,
279    *  this will be the default pattern.
280    */
281   public String toTrueTime(SimTime simTime) {
282     // transform sim time to true time
283     // for this, subtract startSimTime from simTime (both are in reference unit),
284     // convert into milliseconds and then add offset (is in milliseconds)
285     Date trueTime = new Date((long)((simTime.getTimeValue() - this.startSimTime)
286                       * unitFactors[this.unit] / unitFactors[MS]
287                      + this.offset));
288     return this.outFormat.format(trueTime);
289   }
290   /** Converts the given sim time value to the corresponding true time value
291    *  using the given pattern as time format.
292    *  @param simTime SimTime : the sim time value to be converted
293    *  @param pattern String : the time format to be used for formatting the
294    *  true time value
295    *  @return String : the true time representing the given sim time as a
296    *  String formatted according to the given pattern
297    */
298   public String toTrueTime(SimTime simTime, String pattern) {
299     setTimeFormat(pattern);
300     String trueTime = toTrueTime(simTime);
301     resetTimeFormat();
302     return trueTime;
303   }
304 }