date, time (BETA)

// date, time / date

char check_leap_year( short y ) {

	/* USE:
	
	char l = check_leap_year( y );
	
	*/
	
	/* META TAGS:
	
	ALGO: high
	DATE: 2025-03-03 00:05
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date, leap year
	
	*/
	
	char leap = (
	
		( y % 400 == 0 ) // every 400 years
		
		||
		
		(
		
			( y % 4 == 0 ) // every 4 years
			
			&&
			
			!( y % 100 == 0 ) // but not every 100 years
			
		)
		
	);
	
	return leap;
	
} // function

char get_days_of_month_in_non_leap_year( char m ) {

	/* USE:
	
	char d = get_days_of_month_in_non_leap_year( m );
	
	*/
	
	/* META TAGS:
	
	ALGO: high
	DATE: 2025-03-03 00:10
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date, leap year
	
	*/
	
	char dd = 30; // default
	
	if ( m == 2 ) { // February
	
		dd = 28;
	
	} else { // see "https://en.wikipedia.org/wiki/Knuckle_mnemonic"
	
		if ( m <= 7 ) { // left hand
		
			if ( m % 2 == 1 ) dd = 31; // ... starting with odd month number (1, January)
			
		} else { // right hand
		
			if ( m % 2 == 0 ) dd = 31; // ... starting with even month number (8, August)
			
		} // if/else
		
	} // if/else
	
	return dd;
	
} // function

char get_days_of_month( short y, char m ) {

	/* USE:
	
	char d = get_days_of_month( y, m );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-03 00:15
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date, leap year
	
	*/
	
	char leap = check_leap_year( y ); // check leap year
	
	char dd = get_days_of_month_in_non_leap_year( m ); // get days of month, non leap year
	
	if ( ( leap ) && ( m == 2 ) ) dd++; // adjust February, any year
	
	return dd;
	
} // function

// date, time / date / next/previous

void eval_next_year( short *y ) {

	/* USE:
	
	short y = 2022;
	eval_next_year( [&]y );
	
	*/
	
	/* META TAGS:
	
	ALGO: low
	DATE: 2025-03-03 22:00
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	(*y)++;
	
} // function

void eval_prev_year( short *y ) {

	/* USE:
	
	short y = 2022;
	eval_prev_year( [&]y );
	
	*/
	
	/* META TAGS:
	
	ALGO: low
	DATE: 2025-03-03 22:05
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	(*y)--;
	
} // function

void eval_next_month( short *y, char *m ) {

	/* USE:
	
	short y = 2022;
	char m = 12;
	eval_next_month( [&]y, [&]m );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-03 22:10
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	if ( *m == 12 ) {
	
		*m = 1;
		
		eval_next_year( y );
		
	} else {
	
		(*m)++;
		
		// year unchanged
		
	} // if/else
	
} // function

void eval_prev_month( short *y, char *m ) {

	/* USE:
	
	short y = 2023;
	char m = 1;
	eval_prev_month( [&]y, [&]m );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-03 22:15
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	if ( *m == 1 ) {
	
		*m = 12;
		
		eval_prev_year( y );
		
	} else {
	
		(*m)--;
		
		// year unchanged
		
	} // if/else
	
} // function

void eval_next_day( short *y, char *m, char *d ) {
	
	/* USE:
	
	char y = 2022;
	char m = 12;
	char d = 31;
	eval_next_day( [&]y, [&]m, [&]d );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-03 22:25
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	char dd = get_days_of_month( *y, *m );
	
	if ( *d == dd ) {
	
		*d = 1;
		
		eval_next_month( y, m );
		
	} else {
	
		(*d)++;
		
		// year and month unchanged
		
	} // if/else
	
} // function

void eval_prev_day( short *y, char *m, char *d ) {

	/* USE:
	
	short y = 2023;
	char m = 1;
	char d = 1;
	eval_prev_day( [&]y, [&]m, [&]d );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-03 22:30
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	if ( *d == 1 ) {
		
		eval_prev_month( y, m );
		
		*d = get_days_of_month( *y, *m );
		
	} else {
	
		(*d)--;
		
		// year and month unchanged
		
	} // if/else
	
} // function

// date, time / date / comparison, sorting

char compare_date( short ay, char am, char ad, short by, char bm, char bd ) {
	
	/* USE:
	
	short ay = 2024;
	char am = 12;
	char ad = 31;
	
	short by = 2025;
	char bm = 1;
	char bd = 31;
	
	char cp = compare_date( ay, am, ad, by, bm, bd );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-24 15:05
	DESC: see function name
	LANG: C
	LIBR: math.h
	PROC: no
	TAGS: date
	
	*/
	
	long a = 
	
		ay * pow( 100, 2 ) + 
		am * 100 +
		ad;
		
	long b = 
	
		by * pow( 100, 2 ) +
		bm * 100 +
		bd;
	
	char r;
	
	if ( b > a ) r = 1;
	else if ( b == a ) r = 0;
	else r = -1
	
	return r;
	
} // function

void sort_date( short *ay, char *am, char *ad, short *by, char *bm, char *bd ) {
	
	/* USE:
	
	short ay = 2024;
	char am = 12;
	char ad = 31;
	
	short by = 2025;
	char bm = 1;
	char bd = 31;
	
	sort_date( [&]ay, [&]am, [&]ad, [&]by, [&]bm, [&]bd );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-24 17:45
	DESC: see function name
	LANG: C
	LIBR: no
	PROC: yes
	TAGS: date
	
	*/
	
	char cp = compare_date( *ay, *am, *ad, *by, *bm, *bd );
	
	if ( cp == -1 ) {
		
		short y;
		char m;
		char d;
		
		y = *ay;
		m = *am;
		d = *ad;
		
		*ay = *by;
		*am = *bm;
		*ad = *bd;
		
		*by = y;
		*bm = m;
		*bd = d;
		
	} // if
	
} // function

// date, time / date / date difference

long get_days_diff( short ay, char am, char ad, short by, char bm, char bd ) {
	
	/* USE:
	
	short ay = 2024;
	char am = 1;
	char ad = 31;
	
	short by = 2024;
	char bm = 5;
	char bd = 26;
	
	long d = get_days_diff( ay, am, ad, by, bm, bd );

	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-22 17:45
	DESC: see function name
	LANG: C
	PROC: no
	TAGS: date
	
	*/
	
	sort_date( &ay, &am, &ad, &by, &bm, &bd );
	
	short y = ay;
	char m = am;
	char d = ad;
	
	long c = 0;
	
	while ( !
	
		( 
		
			( y == by ) &&
			( m == bm ) &&
			( d == bd )
			
		)
		
	) {
		
		eval_next_day( &y, &m, &d );
		
		c++;
		
	} // while
	
	return c;
	
} // function

// date, time / date / date in future/past

void eval_date_in_future( short ay, char am, char ad, long dd, short *by, char *bm, char *bd ) {
	
	/* USE:
	
	short ay = 2024;
	char am = 12;
	char ad = 1;
	
	long dd = 31;
	
	short by;
	char bm;
	char bd;
	
	eval_date_in_future( ay, am, ad, dd, [&]by, [&]bm, [&]bd );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-22 18:25
	DESC: see function name
	LANG: C
	LIBR: no
	PROC: yes
	TAGS: date
	
	*/
	
	short y = ay;
	char m = am;
	char d = ad;
	
	long i = 0;
	
	for ( i=0; i<dd; i++ ) eval_next_day( &y, &m, &d );
	
	*by = y;
	*bm = m;
	*bd = d;
	
} // function

void eval_date_in_past( short ay, char am, char ad, long dd, short *by, char *bm, char *bd ) {
	
	/* USE:
	
	short ay = 2024;
	char am = 12;
	char ad = 1;
	
	long dd = 30;
	
	short by;
	char bm;
	char bd;
	
	eval_date_in_past( ay, am, ad, dd, [&]by, [&]bm, [&]bd );
	
	*/
	
	/* META TAGS:
	
	ALGO: medium
	DATE: 2025-03-22 18:35
	DESC: see function name
	LANG: C
	LIBR: no
	PROC: yes
	TAGS: date
	
	*/
	
	short y = ay;
	char m = am;
	char d = ad;
	
	long i = 0;
	
	for ( i=0; i<dd; i++ ) eval_prev_day( &y, &m, &d );
	
	*by = y;
	*bm = m;
	*bd = d;
	
} // function

// date, time / time

long get_ss_of_hh_mm_ss( long h, char m, char s ) {
	
	// long ss = get_ss_of_hh_mm_ss( h, m, s );
	
	long ss = h * 3600 + m * 60 + s;
	
	return ss;
	
} // function

void eval_hh_mm_ss_of_ss( long ss, long *h, char *m, char *s ) {
	
	// long h;
	// char m, s;
	// eval_hh_mm_ss_of_ss( ss, [&]h, [&]m, [&]s );
	
	*h = ss / 3600;
	
	ss = ss - ( *h * 3600 );
	
	*m = ss / 60;
	
	ss = ss - ( *m * 60 );
	
	*s = ss;
	
} // function

void eval_ss_diff( int ah, int am, int as, int bh, int bm, int bs, int *ss, int *nd ) {
	
	// int ss, nd;
	// eval_ss_diff( ah, am, as, bh, bm, bs, [&]ss, [&]nd );
	
	int maxss = get_ss_of_hh_mm_ss( 24, 0, 0 );
	
	int ass = get_ss_of_hh_mm_ss( ah, am, as );
	int bss = get_ss_of_hh_mm_ss( bh, bm, bs );
	
	*ss = bss - ass;
	
	*nd = 0; // next day
	
	if ( *ss < 0 ) {
		
		*ss += maxss;
		
		*nd = 1;
		
	} // if
	
} // function

void eval_hh_mm_ss_diff( int ah, int am, int as, int bh, int bm, int bs, int *h, int *m, int *s, int *nd ) {
	
	// int h, m, s, nd;
	// eval_hh_mm_ss_diff( ah, am, as, bh, bm, bs, [&]h, [&]m, [&]s, [&]nd );
	
	int ss;
	
	eval_ss_diff( ah, am, as, bh, bm, bs, &ss, nd );
	
	eval_hh_mm_ss_of_ss( ss, h, m, s );
	
} // function

// date, time / combined

long get_ss_of_dd_hh_mm_ss( int d, int h, int m, int s ) {
	
	// long ss = get_ss_of_dd_hh_mm_ss( d, h, m, s );
	
	long ss = d * 24 * 3600 + get_ss_of_hh_mm_ss( h, m, s );
	
	return ss;
	
} // function

void eval_dd_hh_mm_ss_diff( int ay, int amo, int ad, int ah, int ami, int as, int by, int bmo, int bd, int bh, int bmi, int bs, int *d, int *h, int *m, int *s, int *nd ) {
	
	/*
	
	int d, h, m, s, nd;
	
	eval_dd_hh_mm_ss_diff( 
	
		ay, amo, ad,
		ah, ami, as,
		
		by, bmo, bd,
		bh, bmi, bs,
		
		[&]d, [&]h, [&]m, [&]s,
		[&]nd
		
	);
	
	*/
	
	/*
	
	1.1. 12:00
	1.1. 13:00
	
	0 d, 1 h
	
	1.1. 12:00
	2.1. 11:00
	
	0 d, 23 h
	
	1.1. 12:00
	2.1. 13:00
	
	1 d, 1 h
	
	*/
	
	*d = get_days_diff( ay, amo, ad, by, bmo, bd );
	
	eval_hh_mm_ss_diff( 
	
		ah, ami, as,
		bh, bmi, bs, 
		
		h, m, s,
		
		nd
		
		);
		
	if ( *nd == 1 ) (*d)--;
	
} // function

// date, time / current

void eval_current_date_and_time( int *y, int *mo, int *d, int *h, int *mi, int *s ) {

	/*
	
	int y, mo, d, h, mi, s;
	
	eval_current_date_and_time(
	
	[&]y, [&]mo, [&]d, 
	[&]h, [&]mi, [&]s
	
	);
	
	*/
	
	time_t t = time(NULL);
	
	struct tm tm = *localtime( &t );
	
	// "2024-08-12 12:00:00"
	
	char str[20];
	
	sprintf( 
		
		str,
		
		"%d-%02d-%02d %02d:%02d:%02d",
		
		tm.tm_year + 1900,
		tm.tm_mon + 1,
		tm.tm_mday,
		
		tm.tm_hour,
		tm.tm_min,
		tm.tm_sec
	
	);
	
	sscanf(
		
		str,
		
		"%d-%d-%d %d:%d:%d",
		
		y,
		mo,
		d,
		
		h,
		mi,
		s
		
	);
	
} // function