Home Page
Open Source
Contact Us
Free Downloads
Releases and Credits
Software Status
License
About rrproj
assigning people and/or equipment to projects
High-Hope Technique
History of the AI
View Source Files
and how they are organized
Making Programs
Development Notes
Using aiParts
Your Application
Support and Services
|
|
aiParts Source File
//**********************************************************************
// aipTime.cpp - function bodies for aipTime.h
//
// Copyright (c) 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/07/09 [BRM] fixed a few bugs, improved the structure
// 08/02/03 [BRM] began development
//
//----------------------------------------------------------------------
#include "aipTime.h"
#include <stdio.h>
#include <stdlib.h>
// for debugging...
// #include
// using namespace std;
//======================================================================
// Global Functions
//
//----------------------------------------------------------------------
// set a string from days-since-Sunday - ex: "Mon" from 1
const char * aip_str_day (long imon) {
if (imon < 0 || imon > 6) return aip_Empty_Str;
return aip_Day_Abbrv[imon-1];
}
//----------------------------------------------------------------------
// return the month-number: 1 for "Jan", 2 for "feb", etc.
// or return zero if x is not valid
long aip_i_month (const char* x) {
if (x[0] == 'J' || x[0] == 'j') {
if (x[1] == 'A' || x[1] == 'a') {
if (x[2] == 'N' || x[2] == 'n') return 1;
} else {
if (x[1] == 'U' || x[1] == 'u') {
if (x[2] == 'N' || x[2] == 'n') return 6;
if (x[2] == 'L' || x[2] == 'l') return 7;
}
}
} else if (x[0] == 'F' || x[0] == 'f') {
if (x[1] == 'E' || x[1] == 'e') {
if (x[2] == 'B' || x[2] == 'b') return 2;
}
} else if (x[0] == 'M' || x[0] == 'm') {
if (x[1] == 'A' || x[1] == 'a') {
if (x[2] == 'R' || x[2] == 'r') return 3;
if (x[2] == 'Y' || x[2] == 'y') return 5;
}
} else if (x[0] == 'A' || x[0] == 'a') {
if (x[1] == 'P' || x[1] == 'p') {
if (x[2] == 'R' || x[2] == 'r') return 4;
} else if (x[1] == 'U' || x[1] == 'u') {
if (x[2] == 'G' || x[2] == 'g') return 8;
}
} else if (x[0] == 'S' || x[0] == 's') {
if (x[1] == 'E' || x[1] == 'e') {
if (x[2] == 'P' || x[2] == 'p') return 9;
}
} else if (x[0] == 'O' || x[0] == 'o') {
if (x[1] == 'C' || x[1] == 'c') {
if (x[2] == 'T' || x[2] == 't') return 10;
}
} else if (x[0] == 'N' || x[0] == 'n') {
if (x[1] == 'O' || x[1] == 'o') {
if (x[2] == 'V' || x[2] == 'v') return 11;
}
} else if (x[0] == 'D' || x[0] == 'd') {
if (x[1] == 'E' || x[1] == 'e') {
if (x[2] == 'C' || x[2] == 'c') return 12;
}
}
return 0;
}
//----------------------------------------------------------------------
// set a string from a month number - ex: "Jan" from 1
const char * aip_str_month (long imon) {
if (imon < 1 || imon > 12) return aip_Empty_Str;
return aip_Month_Abbrv[imon-1];
}
//----------------------------------------------------------------------
// Return true if yr is a leap year
int aip_is_leap_year (long yr) {
if (yr%4 == 0 && (yr%100 != 0 || yr%400 == 0) ) return 1;
return 0;
}
//----------------------------------------------------------------------
// Return the number of days in the month and year in ts.
long aip_days_in_month (long yr, long mo) {
if (mo < 1 || mo > 12) return 0;
long dim = aip_Days_In_Month[mo];
if (mo == 2 && aip_is_leap_year(yr)) dim = 29;
return dim;
}
//======================================================================
// aipTime
//
//----------------------------------------------------------------------
// Construct from components
aipTime::aipTime (long a_year, long a_mon, long a_day,
long a_hour, long a_min, long a_sec) {
set (a_year, a_mon, a_day, a_hour, a_min, a_sec);
}
//----------------------------------------------------------------------
// Construct from components packed into two longs (second is optional)
//
// in the optional second argument, seconds is optional -
// 43045 is 4:30:45, 430 is 4:30 am, 1630 is 4:30 pm
aipTime::aipTime (long yyyymmdd, long hhmmss) {
set (yyyymmdd, hhmmss);
}
//----------------------------------------------------------------------
// set from components
//
// Note: all constructors and other set functions call this function
// which attempts to prevent Daylight Savings Time from
// causing problems.
void aipTime::set (long a_year, long a_mon, long a_day,
long a_hour, long a_min, long a_sec) {
if (a_year < 30) a_year += 100; // 2-digit year after 2000
if (a_year < 1000) a_year += 1900; // convert 2-digit year to 4-digit
if (a_year < 1800 || a_year > 2300 ||
a_mon < 1 || a_mon > 12 ||
a_day < 1 || a_day > 31 ||
a_hour < 0 || a_hour > 23 ||
a_min < 0 || a_min > 59 ||
a_sec < 0 || a_sec > 59) return;
struct tm ts; // broken-down time
ts.tm_sec = a_sec;
ts.tm_min = a_min;
ts.tm_hour = a_hour;
ts.tm_mday = a_day;
ts.tm_mon = a_mon - 1;
ts.tm_year = a_year - 1900;
set_daylight_savings_time (&ts);
m_time = mktime (&ts);
}
//----------------------------------------------------------------------
// set from components packed into two longs (second is optional)
//
// 430 is 4:30 am, 1630 is 4:30 pm
void aipTime::set (long yyyymmdd, long hhmm) {
long xyear, xmon, xday, xhour, xmin;
long x = yyyymmdd;
xyear = x / 10000;
x -= (xyear * 10000);
if (xyear < 30) xyear += 100; // 2-digit year after 2000
if (xyear < 200) xyear += 1900; // convert 2-digit year to 4-digit
xmon = x / 100;
x -= (xmon * 100);
xday = x;
x = hhmm;
if (x > 0) {
xhour = x / 100;
x -= (xhour * 100);
xmin = x;
} else {
xhour = xmin = 0;
}
set (xyear, xmon, xday, xhour, xmin, 0);
}
//----------------------------------------------------------------------
// set from another instance of aipTime
void aipTime::set (const aipTime& x) {
m_time = x.tt_time();
}
//----------------------------------------------------------------------
// set from a string like: "17 Feb 1998" or "17/02/2008 16:30:45"
// or insert-format: "2008-02-17"
//
// seconds is optional; hours, minutes, seconds are optional
void aipTime::set (const char *x) {
long xyear, xmon, xday, xhour, xmin, xsec, z;
char buf[31];
xyear = xmon = xday = 0;
xhour = xmin = xsec = 0;
while (x && *x) {
x = aip_get_str(x, 30, buf);
if (x) {
if (buf[0] >= '0' && buf[0] <= '9') {
z = atol(buf);
if (z <= 0) { x=0; break; }
if (z > 31) { // must be year
if (xyear) { x=0; break; } // already have a year
xyear = z;
} else if (!xday && !xmon && !xyear) { // first component
xday = z; // assume dmy
} else if ( xday && !xmon && !xyear) { // month or year
xmon = z; // if day is first, assume dmy
} else if ( xmon && !xday && !xyear) { // day or year
xday = z; // if month is first, assume mdy
} else if ( xyear && !xday && !xmon) { // day or month
xmon = z; // if year is first, assume ymd
} else if ( xday && xmon && !xyear) {
xyear = z;
} else if ( xday && xyear && !xmon) {
xmon = z;
} else if ( xmon && xyear && !xday) {
xday = z;
} else if (!xhour) {
xhour = z;
} else if (!xmin) {
xmin = z;
} else if (!xsec) {
xsec = z;
} else {
x=0; break; // have all numeric components
}
} else { // am or pm or month
for (int i=0; i<3; i++) {
if (buf[i] >= 'a' && buf[i] <= 'z') buf[i] -= ('a' - 'A');
}
if ( (buf[0] == 'A' || buf[0] == 'P') && buf[1] == 'M') {
if (!xmin) { x=0; break; }
if (buf[0] == 'P' && xhour <= 12) xhour += 12;
break; // nothing follows am or pm
} // end of block for when string is am or pm
if (xmon) { x=0; break; } // already have a month
xmon = aip_i_month(buf);
if (xmon < 1 || xmon > 12) { x=0; break; }
} // end of block for a string of letters
} // end of block for successfully getting a string
} // end of loop through date/time components
if (x) {
set (xyear, xmon, xday, xhour, xmin, xsec);
} else {
set(0,0,0,0,0,0);
}
}
//----------------------------------------------------------------------
// compare functions
int aipTime::eq (const aipTime& x) const {
if ( difftime (m_time,x.tt_time()) == 0.0 ) return 1;
return 0;
}
int aipTime::ne (const aipTime& x) const {
if ( difftime (m_time,x.tt_time()) != 0.0 ) return 1;
return 0;
}
int aipTime::lt (const aipTime& x) const {
if ( difftime(m_time,x.tt_time()) < 0.0 ) return 1;
return 0;
}
int aipTime::gt (const aipTime& x) const {
if ( difftime(m_time,x.tt_time()) > 0.0 ) return 1;
return 0;
}
int aipTime::le (const aipTime& x) const {
if ( difftime(m_time,x.tt_time()) <= 0.0 ) return 1;
return 0;
}
int aipTime::ge (const aipTime& x) const {
if ( difftime(m_time,x.tt_time()) >= 0.0 ) return 1;
return 0;
}
//----------------------------------------------------------------------
// Set ts->tm_isdst from the other components
void aipTime::set_daylight_savings_time (struct tm *ts) const {
long start_mon, start_day, end_mon, end_day; // Jan = 1
if (ts->tm_year <= 105) { // 2005 and earlier
start_mon = 4; start_day = 3; end_mon = 10; end_day = 30;
} else if (ts->tm_year == 106) { // 2006
start_mon = 4; start_day = 2; end_mon = 10; end_day = 29;
} else if (ts->tm_year == 107) { // 2007
start_mon = 3; start_day = 11; end_mon = 11; end_day = 4;
} else if (ts->tm_year == 108) { // 2008
start_mon = 3; start_day = 9; end_mon = 11; end_day = 2;
} else if (ts->tm_year == 109) { // 2009
start_mon = 3; start_day = 8; end_mon = 11; end_day = 1;
} else if (ts->tm_year >= 110) { // 2010 and later
start_mon = 3; start_day = 14; end_mon = 11; end_day = 7;
}
long mon = ts->tm_mon + 1;
long day = ts->tm_mday;
long hr = ts->tm_hour;
if ( ( (mon > start_mon) ||
(mon == start_mon && day > start_day) ||
(mon == start_mon && day == start_day && hr >= 2) ) &&
( (mon < end_mon) ||
(mon == end_mon && day < end_day) ||
(mon == end_mon && day == end_day && hr < 2) ) ) {
ts->tm_isdst = 1;
} else {
ts->tm_isdst = 0;
}
}
//----------------------------------------------------------------------
// Add seconds to this date
void aipTime::add_seconds (long num) {
if (!is_valid()) return;
struct tm ts = *(localtime(&m_time));
ts.tm_sec += num;
m_time = mktime (&ts); // mktime will renormalize the date
}
//----------------------------------------------------------------------
// Add hours to this date
void aipTime::add_hours (long num) {
if (!is_valid()) return;
struct tm ts = *(localtime(&m_time));
ts.tm_hour += num;
m_time = mktime (&ts); // mktime will renormalize the date
}
//----------------------------------------------------------------------
// Add days to this date
void aipTime::add_days (long num) {
if (!is_valid()) return;
struct tm ts = *(localtime(&m_time));
ts.tm_mday += num;
m_time = mktime (&ts); // mktime will renormalize the date
}
//----------------------------------------------------------------------
// return the number of days since Sunday
long aipTime::days_since_sunday () const {
struct tm *ts = localtime (&m_time);
return ts->tm_wday;
}
//----------------------------------------------------------------------
// return the number of days since January 1
long aipTime::days_since_jan1 () const {
struct tm *ts = localtime (&m_time);
return ts->tm_yday;
}
//----------------------------------------------------------------------
// return the number of seconds since x
long aipTime::seconds_since (const aipTime& x) const {
long nsec = (long)difftime (m_time, x.tt_time());
return nsec;
}
//----------------------------------------------------------------------
// return the number of minutes since x
long aipTime::minutes_since (const aipTime& x) const {
return (seconds_since(x) / 60);
}
//----------------------------------------------------------------------
// return the number of hours since x
long aipTime::hours_since (const aipTime& x) const {
return (seconds_since(x) / (60 * 60));
}
//----------------------------------------------------------------------
// return the number of days since x
long aipTime::days_since (const aipTime& x) const {
return (seconds_since(x) / (60 * 60 * 24));
}
//----------------------------------------------------------------------
// set the whole days, hours, minutes and seconds since x
void aipTime::time_since (const aipTime& x,
long *pdays, long *phrs,
long *pmins, long *psecs) const {
long nsec = seconds_since(x);
const long sec_per_min = 60;
const long sec_per_hr = 60 * 60;
const long sec_per_day = 60 * 60 * 24;
long days = 0;
if (nsec >= sec_per_day) {
days = nsec / sec_per_day;
nsec -= (days * sec_per_day);
}
long hrs = 0;
if (nsec >= sec_per_hr) {
hrs = nsec / sec_per_hr;
nsec -= (hrs * sec_per_hr);
}
long mins = 0;
if (nsec >= sec_per_min) {
mins = nsec / sec_per_min;
nsec -= (mins * sec_per_min);
}
if (pdays) *pdays = days;
if (phrs) *phrs = hrs;
if (pmins) *pmins = mins;
if (psecs) *psecs = nsec;
}
//----------------------------------------------------------------------
// return the difference in hours after x
long aipTime::hours_after (const aipTime& x) const {
long yr, mon, day, hr;
get (&yr, &mon, &day, &hr);
aipTime a(yr, mon, day, hr, 0, 0);
x.get (&yr, &mon, &day, &hr);
aipTime b(yr, mon, day, hr, 0, 0);
return a.hours_since(b);
}
//----------------------------------------------------------------------
// return the difference in days after x
long aipTime::days_after (const aipTime& x) const {
long yr, mon, day;
get (&yr, &mon, &day);
aipTime a(yr, mon, day, 0, 0, 0);
x.get (&yr, &mon, &day);
aipTime b(yr, mon, day, 0, 0, 0);
return a.days_since(b);
}
//----------------------------------------------------------------------
// get components for non-null pointers - return zero on failure
int aipTime::get (long *a_year, long *a_mon, long *a_day,
long *a_hour, long *a_min, long *a_sec,
char *s_mon, char *s_weekday) const {
if (!is_valid()) {
if (a_year) *a_year = 0;
if (a_mon) *a_mon = 0;
if (a_day) *a_day = 0;
if (a_hour) *a_hour = 0;
if (a_min) *a_min = 0;
if (a_sec) *a_sec = 0;
if (s_mon) s_mon[0] = '\0';
if (s_weekday) s_weekday[0] = '\0';
return 0;
}
struct tm *ts = localtime (&m_time);
if (a_year) *a_year = ts->tm_year + 1900;
if (a_mon) *a_mon = ts->tm_mon + 1;
if (a_day) *a_day = ts->tm_mday;
if (a_hour) *a_hour = ts->tm_hour;
if (a_min) *a_min = ts->tm_min;
if (a_sec) *a_sec = ts->tm_sec;
if (s_mon) aip_strncpy(s_mon, aip_Month_Abbrv[ts->tm_mon], 3);
if (s_weekday) aip_strncpy(s_weekday,
aip_Day_Abbrv[ts->tm_wday], 3);
return 1;
}
//----------------------------------------------------------------------
// write the date to dstr - ex: "17/Jan/2008"
void aipTime::dd_mon_yyyy (char *dstr) const {
if (!dstr) return;
long dyear, dmon, dday;
if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }
const char *smon = aip_str_month(dmon);
sprintf (dstr, "%02ld/%s/%ld", dday, smon, dyear);
}
//----------------------------------------------------------------------
// write the date to dstr - ex: "17/Jan/2008_16:30"
void aipTime::dd_mon_yyyy_hh_mm (char *dstr) const {
if (!dstr) return;
long dyear, dmon, dday, dhour, dmin;
if ( ! get(&dyear,&dmon,&dday,&dhour,&dmin) ) { *dstr='\0'; return; }
const char *smon = aip_str_month(dmon);
sprintf (dstr, "%02ld/%s/%ld_%02ld:%02ld",
dday, smon, dyear, dhour, dmin);
}
//----------------------------------------------------------------------
// write the date to dstr - ex: "01/17/08"
void aipTime::dd_mm_yy (char *dstr) const {
if (!dstr) return;
long dyear, dmon, dday;
if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }
sprintf (dstr, "%02ld/%02ld/%02ld", dday, dmon, dyear%100);
}
//----------------------------------------------------------------------
// write the date to dstr - ex: "01/17/2008"
void aipTime::dd_mm_yyyy (char *dstr) const {
if (!dstr) return;
long dyear, dmon, dday;
if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }
sprintf (dstr, "%02ld/%02ld/%4ld", dday, dmon, dyear);
}
//----------------------------------------------------------------------
// write the date to dstr (insert-format) - ex: "2008-01-17"
void aipTime::yyyy_mm_dd (char *dstr) const {
if (!dstr) return;
long dyear, dmon, dday;
if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }
sprintf (dstr, "%04ld-%02ld-%2ld", dyear, dmon, dday);
}
//----------------------------------------------------------------------
// return the date as a long
long aipTime::yyyymmdd () const {
long dyear, dmon, dday;
if ( ! get(&dyear,&dmon,&dday) ) return 0;
return ( dyear*10000 + dmon*100 + dday );
}
//----------------------------------------------------------------------
// return the hhmm as a long
long aipTime::hhmm () const {
long dyear, dmon, dday, dhour, dmin;
if ( ! get(&dyear,&dmon,&dday,&dhour,&dmin) ) return 0;
return ( dhour*100 + dmin );
}
//======================================================================
// aipTimeOfDay
//
//----------------------------------------------------------------------
// set from components
void aipTimeOfDay::set (long a_hour, long a_min) {
m_hour = a_hour;
m_minute = a_min;
if (m_hour < 0 || m_hour > 23 ||
m_minute < 0 || m_minute > 59) reset();
}
//----------------------------------------------------------------------
// set from another instance of aipTimeOfDay
void aipTimeOfDay::set (const aipTimeOfDay& x) {
set (x.hour(), x.minute());
if (!is_valid()) reset();
}
//----------------------------------------------------------------------
// set from a string - ex: "16:30" or "4:30 pm"
void aipTimeOfDay::set (const char *x) {
long hr, min;
char ampm[2]; // only care whether first char is 'p' or 'P'
if (x && *x) x = aip_get_val(x, 2, &hr);
if (x && *x) x = aip_get_val(x, 2, &min);
if (x && *x) x = aip_get_str(x, 1, ampm);
if (x) {
if (*ampm == 'p' || *ampm == 'P') { // pm
if (hr <= 12) hr += 12; // convert to 24 hour clock
}
}
if (hr == 24) hr = 0;
set (hr, min);
}
//----------------------------------------------------------------------
// compare functions
int aipTimeOfDay::eq (const aipTimeOfDay& x) const {
return m_minute == x.minute() && m_hour == x.hour();
}
int aipTimeOfDay::ne (const aipTimeOfDay& x) const {
return !eq(x);
}
int aipTimeOfDay::lt (const aipTimeOfDay& x) const {
if (m_hour < x.hour()) return 1;
if (m_hour == x.hour()) {
if ( m_minute < x.minute()) return 1;
}
return 0;
}
int aipTimeOfDay::gt (const aipTimeOfDay& x) const {
return !lt(x) && !eq(x);
}
int aipTimeOfDay::le (const aipTimeOfDay& x) const {
return lt(x) || eq(x);
}
int aipTimeOfDay::ge (const aipTimeOfDay& x) const {
return !lt(x);
}
//----------------------------------------------------------------------
// add hours to this time-of-day
void aipTimeOfDay::add_hours (long num) {
m_hour += num;
if (m_hour >= 24) m_hour %= 24;
}
//----------------------------------------------------------------------
// add minutes to this time-of-day
void aipTimeOfDay::add_minutes (long num) {
m_minute += num;
if (m_minute >= 60) {
long nhour = m_minute / 60;
m_minute %= 60;
if (nhour > 0) add_hours(nhour);
}
}
//----------------------------------------------------------------------
// return the number of hours since x
long aipTimeOfDay::hours_since (const aipTimeOfDay& x) {
long nhour = m_hour - x.hour();
return nhour;
}
//----------------------------------------------------------------------
// return the number of minutes since x
long aipTimeOfDay::minutes_since (const aipTimeOfDay& x) {
long nmin = (m_minute - x.minute()) +
(m_hour - x.hour()) * 60;
return nmin;
}
//----------------------------------------------------------------------
// write the time-of-day to the pointer on a 24 hour clock
//
// ex: "08:30" "16:45" writes 6 chars (with null)
void aipTimeOfDay::hh_mm (char *dstr) const {
if (!dstr) return;
sprintf (dstr, "%02d:%02d", m_hour, m_minute);
}
//----------------------------------------------------------------------
// write the time-of-day with seconds to the pointer on a 24 hour clock
//
// ex: "08:30:00" "16:45:00 writes 9 chars (with null)
void aipTimeOfDay::hh_mm_ss (char *dstr) const {
if (!dstr) return;
sprintf (dstr, "%02d:%02d:00", m_hour, m_minute);
}
//----------------------------------------------------------------------
// write the time-of-day to the pointer on a 12 hour clock
//
// ex: "08:30 am" "04:45 pm" writes 9 chars (with null)
void aipTimeOfDay::hh_mm_12 (char *dstr) const {
if (!dstr) return;
int hr = m_hour;
char ampm[3];
if (hr > 12) {
strcpy (ampm, "pm");
hr -= 12;
} else {
strcpy (ampm, "am");
}
sprintf (dstr, "%02d:%02d %s", hr, m_minute, ampm);
}
//----------------------------------------------------------------------
//======================================================================
// License
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to
// whom the Software is furnished to do so, subject to the
// following conditions:
//
// The copyright notice and this license shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//
//**********************************************************************
|