Sequence language

Time sequences and time interval sequences can be defined using time units and/or time entity names. For example

        [MON..FRI]

    is equivalent to [MON..FRI/DAY#DAY] and defines a sequence of days Monday through Friday inclusively (see about 

    usage of # and inclusivity below).

Sequence compile is able to recognize this as a time sequence due to use of time entity names like MON or FRI. In most cases compiler also 

can infer proper time units (e.g. in this case since MON and FRI are days of the week the step and span are inferred as DAY). Time entities of different size, in most cases, can be considered nested. For example a year [generally] consist of 12 months a month consist of four weeks, a week consist of seven days, a day consist of 24 hours etc. This allows for nested time sequences to be defined. For example (in delimited form):

        [2014..2015/yr]:[APR..JUN]:[10/day]:[11..12/hour]

    results in the following sequence

        <Result Trigger="1:1=Thu Apr 10 11:00:00 PDT 2014"/>

        <Result Trigger="2:2=Thu Apr 10 12:00:00 PDT 2014"/>

        <Result Trigger="3:3=Sat May 10 11:00:00 PDT 2014"/>

        <Result Trigger="4:4=Sat May 10 12:00:00 PDT 2014"/>

        <Result Trigger="5:5=Tue Jun 10 11:00:00 PDT 2014"/>

        <Result Trigger="6:6=Tue Jun 10 12:00:00 PDT 2014"/>

        <Result Trigger="7:7=Fri Apr 10 11:00:00 PDT 2015"/>

        <Result Trigger="8:8=Fri Apr 10 12:00:00 PDT 2015"/>

        <Result Trigger="9:9=Sun May 10 11:00:00 PDT 2015"/>

        <Result Trigger="10:10=Sun May 10 12:00:00 PDT 2015"/>

        <Result Trigger="11:11=Wed Jun 10 11:00:00 PDT 2015"/>

        <Result Trigger="12:12=Wed Jun 10 12:00:00 PDT 2015"/>

    or in other words it selects

    - 11th and 12th hours of each enclosing day which is

    - 10th day of the enclosing month which is 

    - sequence of APR, MAY and JUN of enclosing year which is

    - sequence of year 2014 and year 2015


    The same sequence can be defined in structural form as

        <year in="[2014..2015]">

            <month in="[APR..JUN]">

                <day eq="10">

                    <hour in="[11..12]"/>

                </day>

            </month>

        </year>

    or

        <year from="2014" till="2015">

            <month from="APR" till="JUN">

                <day eq="10">

                    <hour from="11" till="12"/>

                </day>

            </month>

        </year>

        

    Note that outermost enclosing time interval is always based on the current time unless explicitly specified 

    (not yet implemented) or the time interval is absolute (e.g. year 2014 is an absolute interval while, month 

    MAY which is relative to the enclosing year). Thus unlimited sequence

        [30../10sec]

    run on Sep 15 19:01 will result in the following sequence of 10-seconds intervals (show first 10 values)

        <Execute Warning="Stopped at 10:10">

            <Result Trigger="1:1=Mon Sep 15 19:01:30 PDT 2014"/>

            <Result Trigger="2:2=Mon Sep 15 19:01:40 PDT 2014"/>

            <Result Trigger="3:3=Mon Sep 15 19:01:50 PDT 2014"/>

            <Result Trigger="4:4=Mon Sep 15 19:02:00 PDT 2014"/>

            <Result Trigger="5:5=Mon Sep 15 19:02:10 PDT 2014"/>

            <Result Trigger="6:6=Mon Sep 15 19:02:20 PDT 2014"/>

            <Result Trigger="7:7=Mon Sep 15 19:02:30 PDT 2014"/>

            <Result Trigger="8:8=Mon Sep 15 19:02:40 PDT 2014"/>

            <Result Trigger="9:9=Mon Sep 15 19:02:50 PDT 2014"/>

            <Result Trigger="10:10=Mon Sep 15 19:03:00 PDT 2014"/>

        </Execute>

    it uses current time as a base point and selects time intervals relative to it.


About interval "sharpening":

    

    As mentioned before, time intervals use current time as the base reference point. There is a choice in behaviour

    of how this base point in time will be used. When time iterator sets enclosing interval boundaries as per sequence 

    definition, it may or may not align nested sub-intervals. 

    For example, a compact definition [SUN..SAT/DAY*HOUR] will generate a sequence of one hour long 

    intervals, one for each day of the week. It does not say however how these one hour intervals will be positioned 

    within each day. One solution is to preserve as much information as possible so if sequence iterator was

    created let's say at 1:00 pm then each consequent interval will also start at 1:00 pm on each day. While it preserves

    some information about point of origin, it is not necessarily the expected behaviour. When defining schedules, for 

    example, people don't expect it to behave differently depending on when schedule was started to execute.

    

    Hence another solution is to always align generated nested intervals boundaries with correspondent enclosing

    intervals. This is called interval "sharpening". That is, when sharp mode is engaged, the generated hourly 

    intervals will start on the correspondent day boundaries (i.e. at 00:00 each day) irrespective of the time when

    sequence iterator was started. Note that sharpening occurs only within the base and all subordinate time units 

    (e.g. if sequence generates hourly intervals then hour, minute, second and millisecond of each interval will be 

    aligned with the enclosing time unit, correspondent daily interval in our example)


    To engage sharp mode:

    In compact style definitions an alternative separator '#' (sharp) can be used instead of '*' (soft) span delimiter.

    In canonical form Sharp="true" attribute can be specified. 

    

    Note that compact mode delimiters can be used without their parameters (e.g. [SUN..SAT/DAY#] will generate a sequence 

    of sharp daily intervals for each day of the week)

    

    Also different sequence types may have different default behaviour. For time intervals sharp mode is enabled by default.

    

About inclusive interval boundaries:

    

    When working with numeric sequences the upper (i.e. "Till") sequence boundary is normally exclusive. That is 

    a definition [1..3] will generate the following values [1, 2]. Note that the upper limit is not a part of the sequence.

    This is familiar and [hopefully] expected behaviour which is useful, for example for sequence concatenation (e.g.

    a concatenation of [1..3] and [3..5] will result in expected [1,2,3,4]).

    However, when working with time intervals (e.g. [MON..FRI]) the expected behaviour is inclusive (i.e. Friday should 

    be included in the sequence). Therefore the default behaviour of time interval sequences is set to be inclusive.

    

    At this point there is no explicit control over this behaviour.

    

About time zones:


    Time zone can be specified using '@' separator ("TimeZone" tag in extended form). 

    For example: [2014..2015/yr@UTC]:[APR..JUN]:[10/day]:[11..12/hour]

    Time zone is parsed by java.util.TimeZone.getTimeZone(String id) where id is the string found after '@' separator.

    Nested time interval iterators inherit time zone automatically so it can be set only on the first one (see example above)

    In case of different time zones defined on different sub-sequences the result is undefined and may vary with implementation. 



Extended time sequence definition syntax is implemented. Now you can specify a sequence like

[2015.MAY.25.14.30min..2015.MAY.26.16/hour]

Which will result in

<ExecuteStatus>

    <Result Trigger="1:1=Mon May 25 14:30:00 PDT 2015"/>

    <Result Trigger="2:2=Mon May 25 15:30:00 PDT 2015"/>

    <Result Trigger="3:3=Mon May 25 16:30:00 PDT 2015"/>

    <Result Trigger="4:4=Mon May 25 17:30:00 PDT 2015"/>

    <Result Trigger="5:5=Mon May 25 18:30:00 PDT 2015"/>

    <Result Trigger="6:6=Mon May 25 19:30:00 PDT 2015"/>

    <Result Trigger="7:7=Mon May 25 20:30:00 PDT 2015"/>

    <Result Trigger="8:8=Mon May 25 21:30:00 PDT 2015"/>

    <Result Trigger="9:9=Mon May 25 22:30:00 PDT 2015"/>

    <Result Trigger="10:10=Mon May 25 23:30:00 PDT 2015"/>

    <Result Trigger="11:11=Tue May 26 00:30:00 PDT 2015"/>

    <Result Trigger="12:12=Tue May 26 01:30:00 PDT 2015"/>

    <Result Trigger="13:13=Tue May 26 02:30:00 PDT 2015"/>

    <Result Trigger="14:14=Tue May 26 03:30:00 PDT 2015"/>

    <Result Trigger="15:15=Tue May 26 04:30:00 PDT 2015"/>

    <Result Trigger="16:16=Tue May 26 05:30:00 PDT 2015"/>

    <Result Trigger="17:17=Tue May 26 06:30:00 PDT 2015"/>

    <Result Trigger="18:18=Tue May 26 07:30:00 PDT 2015"/>

    <Result Trigger="19:19=Tue May 26 08:30:00 PDT 2015"/>

    <Result Trigger="20:20=Tue May 26 09:30:00 PDT 2015"/>

    <Result Trigger="21:21=Tue May 26 10:30:00 PDT 2015"/>

    <Result Trigger="22:22=Tue May 26 11:30:00 PDT 2015"/>

    <Result Trigger="23:23=Tue May 26 12:30:00 PDT 2015"/>

    <Result Trigger="24:24=Tue May 26 13:30:00 PDT 2015"/>

    <Result Trigger="25:25=Tue May 26 14:30:00 PDT 2015"/>

    <Result Trigger="26:26=Tue May 26 15:30:00 PDT 2015"/>

   <Result Trigger="27:27=Tue May 26 16:30:00 PDT 2015"/>

</ExecuteStatus>

As you can see, sequence interval boundaries can now be hierarchical in dot-delimited format e.g. 2015.MAY.25.14.30min means 2015-May-25:14:30. It is not necessary to specify time units on each element as long as there is at least one and you follow the standard time interval hierarchy (i.e. year-month-day-hour-minute-second-millisecond). In the above example, “MAY” is used by the system to match all the numerals with time units (i.e. it recognizes that if MAY is a month then to the left of it must be the year and to the right must be day, hour, minute etc.). For non-standard definitions, you can always specify time unit explicitly (e.g. 2015yr.128doy.15hr, where 2015 is a year, 128 is day of the year and 15 is hour of the day). Only 24 hours format is currently supported.