CronTrigger.cs :  » Business-Application » Quartz-Enterprise-Scheduler » Quartz » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Business Application » Quartz Enterprise Scheduler 
Quartz Enterprise Scheduler » Quartz » CronTrigger.cs
/* 
 * Copyright 2004-2009 James House 
 * 
 * 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.
 * 
 */

/*
 * Previously Copyright (c) 2001-2004 James House
 */


using System;

#if NET_20
using NullableDateTimeSystem.NullableSystem.DateTime;
#else
using Nullables;
#endif

#if NET_35
using TimeZoneSystem.TimeZoneInfo;
#endif

using Quartz.Spi;
using Quartz.Util;

namespace Quartz{
  /// <summary>
  /// A concrete <see cref="Trigger" /> that is used to fire a <see cref="JobDetail" />
  /// at given moments in time, defined with Unix 'cron-like' definitions.
  /// </summary>
  /// <remarks>
  /// <p>
  /// For those unfamiliar with "cron", this means being able to create a firing
  /// schedule such as: "At 8:00am every Monday through Friday" or "At 1:30am
  /// every last Friday of the month".
  /// </p>
  /// 
  /// <p>
  /// The format of a "Cron-Expression" string is documented on the 
  /// <see cref="CronExpression" /> class.
  /// </p>
  /// 
  /// <p>
  /// Here are some full examples: <br />
  /// <table cellspacing="8">
  /// <tr>
  /// <th align="left">Expression</th>
  /// <th align="left"> </th>
  /// <th align="left">Meaning</th>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 0 12 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 12pm (noon) every day" /></td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * *"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am every day" /></td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am every day" /></td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 * * ? *"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am every day" /></td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 * * ? 2005"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am every day during the year 2005" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 * 14 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire every minute starting at 2pm and ending at 2:59pm, every day" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 0/5 14 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 0/5 14,18 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 0-5 14 * * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire every minute starting at 2pm and ending at 2:05pm, every day" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 10,44 14 ? 3 WED"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 2:10pm and at 2:44pm every Wednesday in the month of March." />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * MON-FRI"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 15 * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on the 15th day of every month" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 L * ?"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on the last day of every month" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * 6L"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on the last Friday of every month" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * 6L"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on the last Friday of every month" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * 6L 2002-2005"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005" />
  /// </td>
  /// </tr>
  /// <tr>
  /// <td align="left">"0 15 10 ? * 6#3"" /></td>
  /// <td align="left"> </td>
  /// <td align="left">Fire at 10:15am on the third Friday of every month" />
  /// </td>
  /// </tr>
  /// </table>
  /// </p>
  /// 
  /// <p>
  /// Pay attention to the effects of '?' and '*' in the day-of-week and
  /// day-of-month fields!
  /// </p>
  /// 
  /// <p>
  /// <b>NOTES:</b>
  /// <ul>
  /// <li>Support for specifying both a day-of-week and a day-of-month value is
  /// not complete (you'll need to use the '?' character in on of these fields).
  /// </li>
  /// <li>Be careful when setting fire times between mid-night and 1:00 AM -
  /// "daylight savings" can cause a skip or a repeat depending on whether the
  /// time moves back or jumps forward.</li>
  /// </ul>
  /// </p>
  /// </remarks>
  /// <seealso cref="Trigger"/>
  /// <seealso cref="SimpleTrigger"/>
  /// <seealso cref="TriggerUtils"/>
  /// <author>Sharada Jambula</author>
  /// <author>James House</author>
  /// <author>Contributions from Mads Henderson</author>
    [Serializable]
  public class CronTrigger : Trigger
  {
        private const int YearToGiveupSchedulingAt = 2299;
    private CronExpression cronEx = null;
    private DateTime startTimeUtc = DateTime.MinValue;
        private NullableDateTime endTimeUtc = null;
    private NullableDateTime nextFireTimeUtc = null;
    private NullableDateTime previousFireTimeUtc = null;
        [NonSerialized] private TimeZone timeZone = null;

    /// <summary>
    /// Create a <see cref="CronTrigger" /> with no settings.
    /// </summary>
    /// <remarks>
    /// The start-time will also be set to the current time, and the time zone
    /// will be set the the system's default time zone.
        /// </remarks>
    public CronTrigger()
    {
      StartTimeUtc = DateTime.UtcNow;
#if !NET_35
            TimeZone = TimeZone.CurrentTimeZone;
#else
            TimeZone = TimeZoneInfo.Local;
#endif
    }

        /// <summary>
        /// Create a <see cref="CronTrigger" /> with the given name and default group.
        /// </summary>
        /// <remarks>
        /// The start-time will also be set to the current time, and the time zone
        /// will be set the the system's default time zone.
        /// </remarks>
        /// <param name="name">The name.</param>
        public CronTrigger(string name) : this(name, null)
        {
        }

    /// <summary>
    /// Create a <see cref="CronTrigger" /> with the given name and group.
    /// </summary>
    /// <remarks>
    /// The start-time will also be set to the current time, and the time zone
    /// will be set the the system's default time zone.
        /// </remarks>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    public CronTrigger(string name, string group) : base(name, group)
    {
      StartTimeUtc = DateTime.UtcNow;
#if !NET_35
            TimeZone = TimeZone.CurrentTimeZone;
#else
            TimeZone = TimeZoneInfo.Local;
#endif
        }


    /// <summary>
    /// Create a <see cref="CronTrigger" /> with the given name, group and
    /// expression.
    /// </summary>
    /// <remarks>
    /// The start-time will also be set to the current time, and the time zone
    /// will be set the the system's default time zone.
        /// </remarks>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="cronExpression">The cron expression.</param>
    public CronTrigger(string name, string group, string cronExpression) : base(name, group)
    {
      CronExpressionString = cronExpression;
      StartTimeUtc = DateTime.UtcNow;
#if !NET_35
            TimeZone = TimeZone.CurrentTimeZone;
#else
            TimeZone = TimeZoneInfo.Local;
#endif
        }


    /// <summary>
    /// Create a <see cref="CronTrigger" /> with the given name and group, and
    /// associated with the identified <see cref="JobDetail" />.
    /// </summary>
    /// <remarks>
    /// The start-time will also be set to the current time, and the time zone
    /// will be set the the system's default time zone.
    /// </remarks>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="jobName">Name of the job.</param>
    /// <param name="jobGroup">The job group.</param>
    public CronTrigger(String name, string group, string jobName,
      string jobGroup) : base(name, group, jobName, jobGroup)
    {
      StartTimeUtc = DateTime.UtcNow;
#if !NET_35
            TimeZone = TimeZone.CurrentTimeZone;
#else
            TimeZone = TimeZoneInfo.Local;
#endif
        }

    /// <summary>
    /// Create a <see cref="CronTrigger" /> with the given name and group,
    /// associated with the identified <see cref="JobDetail" />,
    /// and with the given "cron" expression.
    /// </summary>
    /// <remarks>
    /// The start-time will also be set to the current time, and the time zone
    /// will be set the the system's default time zone.
        /// </remarks>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="jobName">Name of the job.</param>
    /// <param name="jobGroup">The job group.</param>
    /// <param name="cronExpression">The cron expression.</param>
    public CronTrigger(string name, string group, string jobName,
      string jobGroup, string cronExpression)
#if !NET_35
      : this(name, group, jobName, jobGroup, DateTime.UtcNow, null, cronExpression, TimeZone.CurrentTimeZone)
#else
      : this(name, group, jobName, jobGroup, DateTime.UtcNow, null, cronExpression, TimeZoneInfo.Local)
#endif
    {
    }

    /// <summary>
    /// Create a <see cref="CronTrigger" /> with the given name and group,
    /// associated with the identified <see cref="JobDetail" />,
    /// and with the given "cron" expression resolved with respect to the <see cref="TimeZone" />.
    /// </summary>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="jobName">Name of the job.</param>
    /// <param name="jobGroup">The job group.</param>
    /// <param name="cronExpression">The cron expression.</param>
    /// <param name="timeZone">The time zone.</param>
    public CronTrigger(string name, string group, string jobName,
      string jobGroup, string cronExpression, TimeZone timeZone)
      : this(name, group, jobName, jobGroup, DateTime.UtcNow, null, cronExpression,
      timeZone)
    {
    }


    /// <summary>
    /// Create a <see cref="CronTrigger" /> that will occur at the given time,
    /// until the given end time.
    /// <p>
    /// If null, the start-time will also be set to the current time, the time
    /// zone will be set the the system's default.
    /// </p>
    /// </summary>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="jobName">Name of the job.</param>
    /// <param name="jobGroup">The job group.</param>
        /// <param name="startTimeUtc">The start time.</param>
    /// <param name="endTime">The end time.</param>
    /// <param name="cronExpression">The cron expression.</param>
    public CronTrigger(string name, string group, string jobName,
      string jobGroup, DateTime startTimeUtc, 
            NullableDateTime endTime, 
            string cronExpression)
      : base(name, group, jobName, jobGroup)
    {
      CronExpressionString = cronExpression;

            if (startTimeUtc == DateTime.MinValue)
      {
                startTimeUtc = DateTime.UtcNow;
      }
      StartTimeUtc = startTimeUtc;
      if (endTime.HasValue)
      {
        EndTimeUtc = endTime;
      }
#if !NET_35
            TimeZone = TimeZone.CurrentTimeZone;
#else
            TimeZone = TimeZoneInfo.Local;
#endif
        }


    /// <summary>
    /// Create a <see cref="CronTrigger" /> with fire time dictated by the
    /// <param name="cronExpression" /> resolved with respect to the specified
    /// <param name="timeZone" /> occuring from the <see cref="startTimeUtc" /> until
    /// the given <paran name="endTimeUtc" />.
    /// </summary>
    /// <param name="name">The name.</param>
    /// <param name="group">The group.</param>
    /// <param name="jobName">Name of the job.</param>
    /// <param name="jobGroup">The job group.</param>
        /// <param name="startTimeUtc">The start time.</param>
    /// <param name="endTime">The end time.</param>
    public CronTrigger(string name, string group, string jobName,
            string jobGroup, DateTime startTimeUtc, 
            NullableDateTime endTime,
      string cronExpression, 
            TimeZone timeZone) : base(name, group, jobName, jobGroup)
    {
      CronExpressionString = cronExpression;

            if (startTimeUtc == DateTime.MinValue)
      {
                startTimeUtc = DateTime.UtcNow;
      }
            StartTimeUtc = startTimeUtc;

      if (endTime.HasValue)
      {
        EndTimeUtc = endTime;
      }
      if (timeZone == null)
      {
#if !NET_35            
        TimeZone = TimeZone.CurrentTimeZone;
#else
                timeZone = TimeZoneInfo.Local;
#endif
      }
      else
      {
        TimeZone = timeZone;
      }
    }

    /// <summary>
    /// Clones this instance.
    /// </summary>
    /// <returns></returns>
    public override object Clone()
    {
      CronTrigger copy = (CronTrigger) MemberwiseClone();
      if (cronEx != null)
      {
          copy.CronExpression = (CronExpression) cronEx.Clone();
      }
      return copy;
    }

    /// <summary>
    /// Gets or sets the cron expression string.
    /// </summary>
    /// <value>The cron expression string.</value>
    public string CronExpressionString
    {
      set
      {
          TimeZone orginalTimeZone = TimeZone;
        cronEx = new CronExpression(value);
        cronEx.TimeZone = orginalTimeZone;
      }
      get { return cronEx == null ? null : cronEx.CronExpressionString; }
    }

    /// <summary>
    /// Set the CronExpression to the given one.  The TimeZone on the passed-in
        /// CronExpression over-rides any that was already set on the Trigger.
    /// </summary>
    /// <value>The cron expression.</value>
    public CronExpression CronExpression
    {
      set
      {
        cronEx = value;
        timeZone = value.TimeZone;
      }
    }

    /// <summary>
    /// Returns the date/time on which the trigger may begin firing. This
    /// defines the initial boundary for trigger firings the trigger
    /// will not fire prior to this date and time.
    /// </summary>
    /// <value></value>
    public override DateTime StartTimeUtc
    {
      get {  return startTimeUtc; }
      set
      {
        NullableDateTime eTime = EndTimeUtc;
        if (eTime.HasValue && eTime.Value < value)
        {
          throw new ArgumentException("End time cannot be before start time");
        }
        
        // round off millisecond...
        DateTime dt = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second);
          DateTimeUtil.AssumeUniversalTime(dt);
                startTimeUtc = dt;
      }
    }


    /// <summary>
    /// Get or sets the time at which the <c>CronTrigger</c> should quit
    /// repeating - even if repeastCount isn't yet satisfied. 
    /// </summary>
    public override NullableDateTime EndTimeUtc
    {
      get { return endTimeUtc; }
      set
      {
        DateTime sTime = StartTimeUtc;
        if (value.HasValue && sTime > value.Value)
        {
          throw new ArgumentException("End time cannot be before start time");
        }

        endTimeUtc = DateTimeUtil.AssumeUniversalTime(value);
      }
    }

    /// <summary>
    /// Returns the next time at which the <see cref="Trigger" /> is scheduled to fire. If
        /// the trigger will not fire again, <see langword="null" /> will be returned.  Note that
        /// the time returned can possibly be in the past, if the time that was computed
        /// for the trigger to next fire has already arrived, but the scheduler has not yet
        /// been able to fire the trigger (which would likely be due to lack of resources
        /// e.g. threads).
        /// </summary>
        ///<remarks>
        /// The value returned is not guaranteed to be valid until after the <see cref="Trigger" />
        /// has been added to the scheduler.
        /// </remarks>
        /// <seealso cref="TriggerUtils.ComputeFireTimesBetween(Trigger, ICalendar , DateTime, DateTime)" />
        /// <returns></returns>
        public override NullableDateTime GetNextFireTimeUtc()
        {
      return nextFireTimeUtc;
    }

    /// <summary>
    /// Returns the previous time at which the <see cref="Trigger" /> fired.
    /// If the trigger has not yet fired, <see langword="null" /> will be returned.
    /// </summary>
        /// <returns></returns>
        public override NullableDateTime GetPreviousFireTimeUtc()
    {
      return previousFireTimeUtc;
    }


    /// <summary>
    /// Sets the next fire time.
    /// <p>
    /// <b>This method should not be invoked by client code.</b>
    /// </p>
    /// </summary>
    /// <param name="fireTime">The fire time.</param>
        public void SetNextFireTime(NullableDateTime fireTime)
    {
      nextFireTimeUtc = DateTimeUtil.AssumeUniversalTime(fireTime);
    }


    /// <summary>
    /// Sets the previous fire time.
    /// <p>
    /// <b>This method should not be invoked by client code.</b>
    /// </p>
    /// </summary>
    /// <param name="fireTime">The fire time.</param>
        public void SetPreviousFireTime(NullableDateTime fireTime)
    {
      previousFireTimeUtc = DateTimeUtil.AssumeUniversalTime(fireTime);
    }


    /// <summary>
        /// Sets the time zone for which the <see cref="CronTrigger.CronExpression" /> of this
        /// <see cref="CronTrigger" /> will be resolved.
        /// </summary>
        /// <remarks>
        /// If <see cref="CronTrigger.CronExpression" /> is set after this
        /// property, the TimeZone setting on the CronExpression will "win".  However
        /// if <see cref="CronExpressionString" /> is set after this property, the
        /// time zone applied by this method will remain in effect, since the 
        /// string cron expression does not carry a time zone!
        /// </remarks>
    /// <value>The time zone.</value>
    public TimeZone TimeZone
    {
      get
      {
        if (cronEx != null)
        {
          return cronEx.TimeZone;
        }

        if (timeZone == null)
        {
#if !NET_35
          timeZone = TimeZone.CurrentTimeZone;
#else
                    timeZone = TimeZoneInfo.Local;
#endif
                }
        return timeZone;
      }
      set
      {
        if (cronEx != null)
        {
          cronEx.TimeZone = value;
        }
        timeZone = value;
      }
    }

    /// <summary>
    /// Returns the next time at which the <see cref="Trigger" /> will fire,
    /// after the given time. If the trigger will not fire after the given time,
    /// <see langword="null" /> will be returned.
    /// </summary>
    /// <param name="afterTimeUtc"></param>
        /// <returns></returns>
        public override NullableDateTime GetFireTimeAfter(NullableDateTime afterTimeUtc)
    {
      if (!afterTimeUtc.HasValue)
      {
        afterTimeUtc = DateTime.UtcNow;
      }

      if (StartTimeUtc > afterTimeUtc.Value)
      {
        afterTimeUtc = DateTimeUtil.AssumeUniversalTime(startTimeUtc).AddSeconds(-1);
      }

            if (EndTimeUtc.HasValue && (afterTimeUtc.Value.CompareTo(EndTimeUtc.Value) >= 0))
            {
                return null;
            }

            NullableDateTime pot = GetTimeAfter(afterTimeUtc.Value);
            if (EndTimeUtc.HasValue && pot.HasValue && pot.Value > EndTimeUtc.Value)
      {
        return null;
      }

      return pot;
    }

    /// <summary>
    /// Returns the last UTC time at which the <see cref="Trigger" /> will fire, if
    /// the Trigger will repeat indefinitely, null will be returned.
    /// <p>
    /// Note that the return time *may* be in the past.
    /// </p>
        /// </summary>
        public override NullableDateTime FinalFireTimeUtc
    {
      get
            {
                NullableDateTime resultTime;
                if (EndTimeUtc.HasValue)
                {
                    resultTime = GetTimeBefore(EndTimeUtc.Value.AddSeconds(1));
                }
                else
                {
                    resultTime = (cronEx == null) ? null : cronEx.GetFinalFireTime();
                }

                if (resultTime.HasValue && resultTime.Value < StartTimeUtc)
                {
                    return null;
                }

                return resultTime;
      }
    }

    /// <summary>
    /// Tells whether this Trigger instance can handle events
    /// in millisecond precision.
    /// </summary>
    /// <value></value>
    public override bool HasMillisecondPrecision
    {
      get { return false; }
    }

    /// <summary>
    /// Used by the <see cref="IScheduler" /> to determine whether or not
    /// it is possible for this <see cref="Trigger" /> to fire again.
    /// <p>
    /// If the returned value is <see langword="false" /> then the <see cref="IScheduler" />
    /// may remove the <see cref="Trigger" /> from the <see cref="IJobStore" />.
    /// </p>
    /// </summary>
    /// <returns></returns>
    public override bool GetMayFireAgain()
    {
      return GetNextFireTimeUtc().HasValue;
    }

    /// <summary>
    /// Validates the misfire instruction.
    /// </summary>
    /// <param name="misfireInstruction">The misfire instruction.</param>
    /// <returns></returns>
    protected override bool ValidateMisfireInstruction(int misfireInstruction)
    {
            return (misfireInstruction == Quartz.MisfireInstruction.CronTrigger.DoNothing) 
                || (misfireInstruction == Quartz.MisfireInstruction.CronTrigger.FireOnceNow)
                || (misfireInstruction == Quartz.MisfireInstruction.SmartPolicy);
      
    }


    /// <summary>
    /// This method should not be used by the Quartz client.
    /// <p>
    /// To be implemented by the concrete classes that extend this class.
    /// </p>
    /// <p>
    /// The implementation should update the <see cref="Trigger" />'s state
    /// based on the MISFIRE_INSTRUCTION_XXX that was selected when the <see cref="Trigger" />
    /// was created.
    /// </p>
    /// </summary>
    /// <param name="cal"></param>
    public override void UpdateAfterMisfire(ICalendar cal)
    {
      int instr = MisfireInstruction;

      if (instr == Quartz.MisfireInstruction.SmartPolicy)
      {
        instr = Quartz.MisfireInstruction.CronTrigger.FireOnceNow;
      }

      if (instr == Quartz.MisfireInstruction.CronTrigger.DoNothing)
      {
                NullableDateTime newFireTime = GetFireTimeAfter(DateTime.UtcNow);

                while (newFireTime.HasValue && cal != null
               && !cal.IsTimeIncluded(newFireTime.Value))
        {
          newFireTime = GetFireTimeAfter(newFireTime);
        }
        SetNextFireTime(newFireTime);
      }
      else if (instr == Quartz.MisfireInstruction.CronTrigger.FireOnceNow)
      {
        SetNextFireTime(DateTime.UtcNow);
      }
    }


    /// <summary>
    /// <p>
    /// Determines whether the date and (optionally) time of the given Calendar 
    /// instance falls on a scheduled fire-time of this trigger.
    /// </p>
    /// 
    /// <p>
    /// Equivalent to calling <see cref="WillFireOn(DateTime, bool)" />.
    /// </p>
    /// </summary>
    /// <param name="test">The date to compare.</param>
    /// <returns></returns>
    public bool WillFireOn(DateTime test)
    {
      return WillFireOn(test, false);
    }


    /// <summary>
    /// Determines whether the date and (optionally) time of the given Calendar 
    /// instance falls on a scheduled fire-time of this trigger.
    /// <p>
    /// Note that the value returned is NOT validated against the related
    /// ICalendar (if any).
    /// </p>
    /// </summary>
    /// <param name="test">The date to compare</param>
    /// <param name="dayOnly">If set to true, the method will only determine if the
    /// trigger will fire during the day represented by the given Calendar
    /// (hours, minutes and seconds will be ignored).</param>
    /// <returns></returns>
    public bool WillFireOn(DateTime test, bool dayOnly)
    {
      test = new DateTime(test.Year, test.Month, test.Day, test.Hour, test.Minute, test.Second);
      if (dayOnly)
      {
        test = new DateTime(test.Year, test.Month, test.Day, 0, 0, 0);
      }
            DateTimeUtil.AssumeUniversalTime(test);

            NullableDateTime fta = GetFireTimeAfter(test.AddMilliseconds(-1 * 1000));
#if !NET_35
            DateTime p = TimeZone.ToLocalTime(fta.Value);
#else
            DateTime p = TimeZoneInfo.ConvertTimeFromUtc(fta.Value, TimeZone);
#endif

      if (dayOnly)
      {
        return (p.Year == test.Year
                && p.Month == test.Month
                && p.Day == test.Day);
      }

      while (fta.Value < test)
      {
        fta = GetFireTimeAfter(fta);
      }

      if (fta.Equals(test))
      {
        return true;
      }   

      return false;
    }

    /// <summary>
    /// Called when the <see cref="IScheduler" /> has decided to 'fire'
    /// the trigger (Execute the associated <see cref="IJob" />), in order to
    /// give the <see cref="Trigger" /> a chance to update itself for its next
    /// triggering (if any).
    /// </summary>
    /// <param name="cal"></param>
    /// <seealso cref="JobExecutionException" />
    public override void Triggered(ICalendar cal)
    {
      previousFireTimeUtc = nextFireTimeUtc;
      nextFireTimeUtc = GetFireTimeAfter(nextFireTimeUtc);

      while (nextFireTimeUtc.HasValue && cal != null
             && !cal.IsTimeIncluded(nextFireTimeUtc.Value))
      {
        nextFireTimeUtc = GetFireTimeAfter(nextFireTimeUtc);
      }
    }

    /// <summary>
    /// Updates the trigger with new calendar.
    /// </summary>
    /// <param name="calendar">The calendar to update with.</param>
    /// <param name="misfireThreshold">The misfire threshold.</param>
    public override void UpdateWithNewCalendar(ICalendar calendar, TimeSpan misfireThreshold)
    {
      nextFireTimeUtc = GetFireTimeAfter(previousFireTimeUtc);

            if (!nextFireTimeUtc.HasValue || calendar == null)
            {
                return;
            }

      DateTime now = DateTime.UtcNow;

      while (nextFireTimeUtc.HasValue && !calendar.IsTimeIncluded(nextFireTimeUtc.Value))
      {
        nextFireTimeUtc = GetFireTimeAfter(nextFireTimeUtc);

                if (!nextFireTimeUtc.HasValue)
                {
                    break;
                }

                // avoid infinite loop
                if (nextFireTimeUtc.Value.Year > YearToGiveupSchedulingAt)
                {
                    nextFireTimeUtc = null;
                }

          if (nextFireTimeUtc.HasValue && nextFireTimeUtc.Value < (now))
          {
            TimeSpan diff = now - nextFireTimeUtc.Value;
            if (diff >= misfireThreshold)
            {
              nextFireTimeUtc = GetFireTimeAfter(nextFireTimeUtc);
              continue;
            }
          }
            }
    }


    /// <summary>
    /// Called by the scheduler at the time a <see cref="Trigger" /> is first
    /// added to the scheduler, in order to have the <see cref="Trigger" />
    /// compute its first fire time, based on any associated calendar.
    /// <p>
    /// After this method has been called, <see cref="GetNextFireTimeUtc" />
    /// should return a valid answer.
    /// </p>
    /// </summary>
    /// <param name="cal"></param>
    /// <returns>
    /// the first time at which the <see cref="Trigger" /> will be fired
    /// by the scheduler, which is also the same value <see cref="GetNextFireTimeUtc" />
    /// will return (until after the first firing of the <see cref="Trigger" />).
    /// </returns>
        public override NullableDateTime ComputeFirstFireTimeUtc(ICalendar cal)
        {
      nextFireTimeUtc = GetFireTimeAfter(startTimeUtc.AddSeconds(-1));

      while (nextFireTimeUtc.HasValue && cal != null && !cal.IsTimeIncluded(nextFireTimeUtc.Value))
      {
        nextFireTimeUtc = GetFireTimeAfter(nextFireTimeUtc);
      }

      return nextFireTimeUtc;
    }

    /// <summary>
    /// Gets the expression summary.
    /// </summary>
    /// <returns></returns>
    public string GetExpressionSummary()
    {
      return cronEx == null ? null : cronEx.GetExpressionSummary();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Computation Functions
    //
    ////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Gets the next time to fire after the given time.
    /// </summary>
    /// <param name="afterTime">The time to compute from.</param>
    /// <returns></returns>
        protected NullableDateTime GetTimeAfter(DateTime afterTime)
        {
            if (cronEx != null)
            {
                return cronEx.GetTimeAfter(afterTime);
            }
            else
            {
                return null;
            }
    }

    /// <summary>
    /// NOT YET IMPLEMENTED: Returns the time before the given time
        /// that this <see cref="CronTrigger" /> will fire.
    /// </summary>
    /// <param name="date">The date.</param>
    /// <returns></returns> 
        protected NullableDateTime GetTimeBefore(NullableDateTime date)
    {
            return (cronEx == null) ? null : cronEx.GetTimeBefore(endTimeUtc);
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.