Last active
August 29, 2015 14:01
-
-
Save luelista/4bda8c0c5e08c11d3311 to your computer and use it in GitHub Desktop.
Workingdays - Calculate the number of business days in a given year
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Workingdays - Calculate the number of business days in a given year | |
// Copyright (c) 2014 Max Weller | |
// COMPILE AND RUN: | |
// $ gcc -o workingdays workingdays.c | |
// $ ./workingdays -h | |
// Tested with Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) (x86_64-apple-darwin13.1.0) | |
// and gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) (x86_64-linux-gnu) | |
#include <stdio.h> | |
#include <time.h> | |
#include <string.h> | |
#include <stdlib.h> | |
// definition of months | |
#define JAN 0x0 | |
#define FEB 0x1 | |
#define MAR 0x2 | |
#define APR 0x3 | |
#define MAY 0x4 | |
#define JUN 0x5 | |
#define JUL 0x6 | |
#define AUG 0x7 | |
#define SEP 0x8 | |
#define OCT 0x9 | |
#define NOV 0xa | |
#define DEC 0xb | |
#define TMOBJ struct tm* | |
#define DAYSOFYEAR 365 | |
#define IFDAY(myday,d,m) if ((myday->tm_mon == m) && (myday->tm_mday == d)) | |
#define HOLYDAY(d,m,f,n) IFDAY(myday,d,m) MAKEHOLY(d,m,f,n) | |
#define EASTERDAY(since,f,n) if (march == since) MAKEHOLY(myday->tm_mday,myday->tm_mon,f,n) | |
#define MAKEHOLY(d,m,f,n) { work[day] = f; if(debug)printf("%02d.%02d.\t%s\n", d, 1+m, n); } | |
int debug = 0; | |
float sumdays(); | |
void checkdays(int year); | |
TMOBJ makemyday(int year, int month, int day); | |
void nextday(TMOBJ day); | |
int easter(int X); | |
int urlaubdays(int year, int start, int jahres); | |
float work[DAYSOFYEAR]; | |
// format a day of year | |
char* prnday(int y, int dayofj) { | |
return asctime(makemyday(y-1900, 0, dayofj)); | |
} | |
// main entry point | |
int main(int argc, char** argv) { | |
time_t t = time(NULL); | |
TMOBJ now = localtime(&t); | |
int year = 0; | |
int ju = -1; | |
// parse opts | |
if (argc == 1) year = now->tm_year + 1900; | |
else if (argc == 2 && strcmp(argv[1], "-c") == 0) { year = now->tm_year + 1900; debug = 1; } | |
else if (argc == 2) year = atoi(argv[1]); | |
else if (argc == 3 && strcmp(argv[1], "-c") == 0) { year = atoi(argv[2]); debug = 1; } | |
else if (argc == 4 && strcmp(argv[1], "-j") == 0) { year = atoi(argv[2]); ju = atoi(argv[3]); } | |
// show usage | |
if (year == 0) { | |
printf("Usage: %1$s [-c] [year]\n\ | |
or %1$s -j year annualVacationDays\n\n\ | |
-c display holiday dates and names\n\ | |
-j calculate maximum free time\n", argv[0]); | |
return 1; | |
} | |
// run calculation | |
checkdays(year); | |
printf("%f\n", sumdays()); | |
if (ju > -1) { | |
int maxu = 0, maxi = 0, i, u; | |
for(i = 0; i <= DAYSOFYEAR - ju; i++) { | |
u = urlaubdays(year, i, ju); | |
if (u > maxu) { maxu = u; maxi = i; } | |
} | |
printf("You get the maximum free time of %d days if you start your vacation on %s", maxu, prnday(year, maxi+1)); | |
} | |
return 0; | |
} | |
// count the holidays | |
float sumdays() { | |
float sum = 0.0; int i; | |
for(i = 0; i <= DAYSOFYEAR; i++) sum += work[i]; | |
return sum; | |
} | |
// go through year and check holidays | |
void checkdays(int year) { | |
int e = easter(year); | |
year -= 1900; | |
TMOBJ myday = makemyday(year, 0, 1); | |
int day = 0, march = 0; | |
while(myday->tm_year == year) { | |
if (myday->tm_mon >= MAR) march++; | |
work[day] = 1.0; | |
if (myday->tm_wday < 2) work[day] = 0.0; | |
// definition of fixed holidays | |
// day month work holiday name | |
HOLYDAY( 1, JAN, 0.0, "Neujahr"); | |
HOLYDAY( 1, MAY, 0.0, "Maifeiertag"); | |
HOLYDAY( 3, OCT, 0.0, "Tag der Deutschen Einheit"); | |
HOLYDAY( 24, DEC, 0.5, "Heiligabend"); | |
HOLYDAY( 25, DEC, 0.0, "1. Weihnachtsfeiertag"); | |
HOLYDAY( 26, DEC, 0.0, "2. Weihnachtsfeiertag"); | |
// definition of movable holidays dependent on easter sunday | |
// delta work holiday name | |
EASTERDAY( e - 2, 0.5, "Karfreitag"); | |
EASTERDAY( e + 1, 0.0, "Ostermontag"); | |
EASTERDAY( e + 39, 0.0, "Christi Himmerfahrt"); | |
EASTERDAY( e + 50, 0.0, "Pfingstmontag"); | |
nextday(myday); day++; | |
} | |
} | |
// return a pointer to a time structure with the given date | |
TMOBJ makemyday(int year, int month, int day) { | |
time_t t = time(NULL); | |
TMOBJ now = localtime(&t); | |
now->tm_mon = month; now->tm_mday = day; now->tm_year = year; | |
now->tm_hour = 1; now->tm_min = 0; now->tm_sec = 0; | |
t = mktime(now); | |
TMOBJ first = localtime(&t); | |
return first; | |
} | |
// increment a time structure by one day | |
void nextday(TMOBJ day) { | |
day->tm_mday++; | |
time_t mytime = mktime(day); | |
day = localtime(&mytime); | |
} | |
// calculate easter day according to the Gaussian formula | |
int easter(int X) { | |
int K = X / 100; | |
int M = 15 + (3 * K + 3) / 4 - (8 * K + 13) / 25; | |
int S = 2 - (3 * K + 3) / 4; | |
int A = X % 19; | |
int D = (19 * A + M) % 30; | |
int R = (D + A / 11) / 29; | |
int OG = 21 + D - R; | |
int SZ = 7 - (X + X / 4 + S) % 7; | |
int OE = 7 - (OG - SZ) % 7; | |
int OS = OG + OE; | |
return OS; | |
} | |
int urlaubdays(int year, int start, int jahres) { | |
int i; float j = jahres; | |
for(i = start; i <= DAYSOFYEAR && j > 0; i++) { | |
j -= work[i]; | |
} | |
return i - start; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment