Visit Jeremy's Blog.
 Home Forums HCL Reviews Tutorials Articles Register Search Today's Posts Mark Forums Read
 LinuxQuestions.org Time question, Tough!
 Programming This forum is for all programming questions. The question does not have to be directly related to Linux and any language is fair game.

Notices

 04-10-2011, 07:30 PM #16 Nominal Animal Senior Member   Registered: Dec 2010 Location: Finland Distribution: Xubuntu, CentOS, LFS Posts: 1,723 Blog Entries: 3 Rep: My approach differs a bit from wje_lq's. My workdays() takes the two dates as unix timestamps (time_t), and a 7-bit mask describing which days of week are work days. The function returns the number of work days between the two dates in the local time zone, inclusive. My version is thread-safe, and does not modify the environment (or locale or time zone) during the calculation. It does expect the time zone not to change while it runs, though. My workdays() function makes the following assumptions:localtime_r() converts a time_t to struct tm in the local timezone, and sets the tm_wday field to 0 for Sunday, 1 for Monday, .., 6 for Saturday (localtime_t() is also thread-safe, whereas localtime() is not.) mktime() converts a struct tm in local timezone to time_t difftime() returns the number of seconds between two time_t timestamps, and it is about 86400 seconds for each day (In any interval, there should be less than 28800 seconds (eight hours) of drift, including DST and other adjustments) The logic in the calculation is simple: Calculate the number of days in the initial fractional week (zero if the interval is full weeks), plus the number of weeks in the interval multiplied by the number of workdays in a week. The initial fractional week is best described using a bit pattern, since the work week is also described using a bit pattern. The left side in the & expression is a string of one bits the fractional week long, and the right side is the work week adjusted to start from the initial date in the interval. (Since the string of one bits is at most 6 bits long, it does not matter if there are a few extra bits in the right side.) The result is the correct bit pattern for the initial fractional week, and it will be empty (zero) if the interval is full weeks. I've only tested the code lightly, so there may still be some bugs lurking in it. Code: ```#define _XOPEN_SOURCE #include #include #include /* These are the bit masks for workdays(). */ #define SUNDAY (1U) #define MONDAY (2U) #define TUESDAY (4U) #define WEDNESDAY (8U) #define THURSDAY (16U) #define FRIDAY (32U) #define SATURDAY (64U) /* This is the constant for Monday to Friday work week. */ #define MON_FRI (62U) /* Return the number of bits set in mask, AKA __builtin_popcount(). */ static inline uint32_t popcount(uint32_t value) { uint32_t const mask1 = 0x55555555; uint32_t const mask2 = 0xc30c30c3; value -= (value >> 1U) & mask1; value = (value & mask2) + ((value >> 2U) & mask2) + ((value >> 4U) & mask2); value += (value >> 6U); return (value + (value >> 12U) + (value >> 24U)) & 63U; } /* Return the number of workdays between the two dates, inclusive. * This uses the current time zone settings. */ int workdays(time_t from_time, time_t to_time, unsigned int const work_week) { uint32_t const week = (uint32_t)(work_week & 127U); uint32_t const fortnight = week | (week << 7U); struct tm from_tm, to_tm; int days; if (from_time < to_time) { localtime_r(&from_time, &from_tm); localtime_r(&to_time, &to_tm); } else { localtime_r(&from_time, &to_tm); localtime_r(&to_time, &from_tm); } /* Use 8 hours of buffer in any direction */ from_tm.tm_hour = 8; to_tm.tm_hour = 16; from_tm.tm_min = 0; to_tm.tm_min = 0; from_tm.tm_sec = 0; to_tm.tm_sec = 0; from_tm.tm_isdst = 0; to_tm.tm_isdst = 0; from_time = mktime(&from_tm); to_time = mktime(&to_tm); days = 1 + (int)(difftime(to_time, from_time) / 86400.0); return (int)popcount( (127U >> (7 - (days % 7))) & (fortnight >> from_tm.tm_wday) ) + (int)popcount( week ) * (int)(days / 7); } int local_noon(char const *date, time_t *const where) { struct tm tm; if (!date) { if (where) { time_t now = time(NULL); localtime_r(&now, &tm); tm.tm_hour = 12; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; *where = mktime(&tm); } return 0; } if (strptime(date, "%Y-%m-%d", &tm) || strptime(date, "%Y%m%d", &tm) || strptime(date, "%m/%d/%Y", &tm) || strptime(date, "%d.%m.%Y", &tm)) { if (where) { tm.tm_hour = 12; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; *where = mktime(&tm); } return 0; } return -1; } int main(int argc, char *argv[]) { time_t time1, time2; if (argc < 2 || argc > 3) { fprintf(stderr, "Usage: yyyy-mm-dd [ yyyy-mm-dd ]\n"); return (argc == 1) ? 0 : 1; } if (local_noon(argv[1], &time1)) { fprintf(stderr, "%s: Invalid date.\n", argv[1]); return 1; } if (argc > 2) { if (local_noon(argv[2], &time2)) { fprintf(stderr, "%s: Invalid date.\n", argv[2]); return 1; } } else local_noon(NULL, &time2); printf("%d\n", workdays(time1, time2, MON_FRI)); return 0; }```
04-10-2011, 10:04 PM   #17
ted_chou12
Member

Registered: Aug 2010
Location: Zhongli, Taoyuan
Distribution: slackware, windows, debian (armv4l GNU/Linux)
Posts: 430
Blog Entries: 28

Rep:
Quote:
 Originally Posted by paulsm4 wge_lq - No. Think about it! Why *not* define a "day" as a "period of time lasting exactly 86400 seconds"? It all depends on exactly what we're trying to measure. Often times, it's better ("more accurate", "more meaningful", "more precise") to NOT get caught up in minutia like "leap seconds" and "daylight savings time". The "correct answer" to ANY question is seldom "yes" or "no". It's usually "It depends"
I was going to have a try at this b4, but when I thought about this and some other uncertainties, eg. in the first post, he didnt count the day started on. I gave up. Probably need more information to go with afterall.

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is Off HTML code is Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post Manish87 Linux - Newbie 5 06-30-2010 12:55 PM networkingnub Linux - Networking 3 07-19-2009 10:13 PM WickedAwsome Linux - Hardware 5 06-16-2006 04:55 PM pjz Programming 4 03-24-2005 03:05 PM Cobra133 Linux - Software 1 06-28-2004 09:34 AM

LinuxQuestions.org

All times are GMT -5. The time now is 05:07 AM.

 Contact Us - Advertising Info - Rules - LQ Merchandise - Donations - Contributing Member - LQ Sitemap -