TimeOfDay.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:7k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: TimeOfDay.c++,v 1.1.1.1 2005/11/11 21:32:03 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. #include "TimeOfDay.h"
  27. #include <ctype.h>
  28. class Sys {
  29. public:
  30.     static struct tm* localtime(time_t& t) { return ::localtime(&t); }
  31. };
  32. #define BIT(x) (1<<(x))
  33. TimeOfDay::TimeOfDay() : tod(0xff, 0, 24*60) // any day, any time
  34. {
  35. }
  36. TimeOfDay::TimeOfDay(const TimeOfDay& other) : tod(other.tod)
  37. {
  38.     for (_tod* t = other.tod.next; t; t = t->next)
  39. add(t->days, t->start, t->end);
  40. }
  41. TimeOfDay::~TimeOfDay()
  42. {
  43.     reset();
  44. }
  45. void
  46. TimeOfDay::reset()
  47. {
  48.     if (tod.days != 0xff) {
  49. _tod* next;
  50. for (_tod* t = tod.next; t; t = next) {
  51.     next = t->next;
  52.     delete t;
  53. }
  54. tod.days = 0xff;
  55. tod.start = 0;
  56. tod.end = 24*60;
  57. tod.next = NULL;
  58.     }
  59. }
  60. void
  61. TimeOfDay::add(int days, time_t start, time_t end)
  62. {
  63.     if (tod.days == 0xff) { // NB: 0xff means initialized by constructure
  64. tod.days = days;
  65. tod.start = start;
  66. tod.end = end;
  67.     } else {
  68. _tod* t = new _tod(days, start, end);
  69. _tod** tpp;
  70. for (tpp = &tod.next; *tpp; tpp = &(*tpp)->next)
  71.     ;
  72. *tpp = t;
  73.     }
  74. }
  75. /*
  76.  * Parse time-to-send specification string and generate
  77.  * an internal format that's easy to check against a
  78.  * struct tm time.
  79.  *
  80.  *    Syntax = tod ["," tod]
  81.  *       tod = <days><timerange>
  82.  *      days = "Any" | "Wk" | <dayname>+ | nothing
  83.  *   dayname = "Sun" | "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat"
  84.  * timerange = <start> "-" <end> | nothing
  85.  *     start = <24hrtime>
  86.  *       end = <24hrtime>
  87.  *  24hrtime = {0-9}{0-9}{0-9}{0-9}
  88.  *
  89.  * where start & end are 24-hour times, day names can be either
  90.  * 2- or 3-characters, and a null day or time specification means
  91.  * any time or day.  For example,
  92.  *
  93.  *    Any any time of any day
  94.  *    MoWeFri0800-0900 Monday+Wednesday+Friday between 8am and 9am
  95.  *    2330-0130 any day, between 11:30pm and 1:30am the next day
  96.  *    TueThu any time on Tuesday and Thursday
  97.  *
  98.  * White space and other syntactic sugar may be freely inserted between
  99.  * tokens:
  100.  *
  101.  *    MoWeFri/0800-0900 Monday+Wednesday+Friday between 8am and 9am
  102.  *    Tue+Thu any time on Tuesday and Thursday
  103.  *
  104.  * but may not be inserted between 24-hour times in the time range.
  105.  */
  106. void
  107. TimeOfDay::parse(const char* cp)
  108. {
  109.     reset();
  110.     while (*cp != '') {
  111. while (isspace(*cp))
  112.     cp++;
  113. int days = 0;
  114. if (strneq(cp, "Any", 3)) { // any day
  115.     days = 0x7f;
  116.     cp += 3;
  117. } else if (strneq(cp, "Wk", 2)) { // any week day
  118.     days = 0x3e;
  119.     cp += 2;
  120. } else if (isalpha(*cp)) { // list of days
  121.     do {
  122. static const char* dayNames = "Sun Mon Tue Wed Thu Fri Sat ";
  123. u_int i;
  124. for (i = 0; dayNames[i] != ''; i += 4)
  125.     if (cp[0] == dayNames[i] && cp[1] == dayNames[i+1])
  126. break;
  127. if (dayNames[i] == '') {
  128.     // XXX unknown day
  129.     break;
  130. }
  131. days |= BIT(i>>2);
  132. cp += (cp[2] == dayNames[i+2] ? 3 : 2);
  133. for (; !isalnum(*cp) && *cp != ',' && *cp; cp++)
  134.     ;
  135.     } while (isalpha(*cp));
  136. }
  137. if (days == 0)
  138.     days = 0x7f; // default to any day
  139. // skip to any time range
  140. while (*cp && *cp != ',' && !isdigit(*cp))
  141.     cp++;
  142. unsigned start, end;
  143. if (sscanf(cp, "%u-%u", &start, &end) == 2) {
  144.     // convert from military time to seconds
  145.     start = (start/100)*60 + (start%100);
  146.     end = (end/100)*60 + (end%100);
  147. } else {
  148.     // no time spec or invalid spec, use all day
  149.     start = 0;
  150.     end = 24*60;
  151. }
  152. add(days, start, end);
  153. // skip to next time-of-day specification
  154. while (*cp && *cp++ != ',')
  155.     ;
  156.     }
  157. }
  158. /*
  159.  * Return the next time of day that's OK.
  160.  */
  161. time_t
  162. TimeOfDay::nextTimeOfDay(time_t t) const
  163. {
  164.     struct tm* tm = Sys::localtime(t);
  165.     time_t best = 7*24*60+1; // 1 week+1 minute 
  166.     time_t hm = tm->tm_hour*60 + tm->tm_min;
  167.     for (const _tod* td = &tod; td; td = td->next) {
  168. time_t diff = td->nextTime(tm->tm_wday, hm);
  169. if (diff < best)
  170.     best = diff;
  171.     }
  172.     return (t + 60*best);
  173. }
  174. _tod::_tod(int d, time_t s, time_t e)
  175. {
  176.     days = d;
  177.     start = s;
  178.     end = e;
  179.     next = NULL;
  180. }
  181. _tod::_tod(const _tod& other)
  182. {
  183.     days = other.days;
  184.     start = other.start;
  185.     end = other.end;
  186.     next = NULL;
  187. }
  188. /*
  189.  * Starting at wday+d, look for an OK day.
  190.  */
  191. int
  192. _tod::nextDay(int d, int wday) const
  193. {
  194.     for (int w = (wday+d)%7; (days & BIT(w)) == 0; w = (w+1)%7)
  195. d++;
  196.     return d;
  197. }
  198. /*
  199.  * Calculate the time differential to the next
  200.  * time at which <wday,hm> is acceptable.  Note
  201.  * that 0 means it's OK right now.
  202.  */
  203. time_t
  204. _tod::nextTime(int wday, time_t hm) const
  205. {
  206.     int d = (days & BIT(wday)) ? 0 : nextDay(1, wday);
  207.     time_t mins;
  208.     if (start <= end) {
  209. if (start <= hm) {
  210.     if (end < hm) { // outside time range
  211. mins = (24*60-hm)+start;// time to next start of range
  212. if (d == 0) // find next available day
  213.     d = nextDay(d+1, wday);
  214. d--; // time includes day forward
  215.     } else { // within time range
  216. if (d != 0) { // backup to start of range
  217.     mins = (24*60-hm)+start;
  218.     d--; // time includes day forward
  219. } else // ok to go now
  220.     mins = 0;
  221.     }
  222. } else { // before start of range
  223.     mins = start - hm; // push to start of range
  224. }
  225.     } else {
  226. if (start <= hm) { // within time range
  227.     if (d != 0) { // backup to start of range
  228. mins = (24*60-hm)+start;
  229. d--; // time includes day forward
  230.     } else // ok to go now
  231. mins = 0;
  232. } else {
  233.     if (end < hm) // outside time range, push to start
  234. mins = start - hm;
  235.     else // ok to go now
  236. mins = 0;
  237. }
  238.     }
  239.     return (d*24*60 + mins);
  240. }