cDuration
Overview / Purpose
The cDuration module provides the cDuration struct and functions to manipulate and interprete it. A cDuration value represents a duration of time measured in nanoseconds. A cDuration can be positive or negative, for both cases is the maximum value 15250w 1d 23h 47m 16.854775807s, thats approximately 290 years. Every higher/lower value will be a null cDuration value that is invalid.
Types and Definitions
cDuration
struct cDuration
{
int64_t _v;
};
typedef struct cDuration cDuration;
The cDuration struct has just the attribute _v that safes the internal value. It should not be accessd directly.
Generated
cDurationSlice
struct cDurationSlice
{
int64_t s;
cDuration const* v;
};
typedef struct cDurationSlice cDurationSlice;
Via the macro SLICES_C_ generated struct.
cVarDurationSlice
struct cVarDurationSlice
{
int64_t s;
cDuration* v;
};
typedef struct cVarDurationSlice cVarDurationSlice;
Via the macro SLICES_C_ generated struct.
Definitions
C_Week
int64_t const C_Week = 7L*24L*60L*60L*1000L*1000L*1000L;
Defines the multiplication factor to convert a week count to a duration value.
C_Day
int64_t const C_Day = 24L*60l*60L*1000L*1000L*1000L;
Defines the multiplication factor to convert a day count to a duration value.
C_Hour
int64_t const C_Hour = 60L*60L*1000L*1000L*1000L;
Defines the multiplication factor to convert a hour count to a duration value.
C_Min
int64_t const C_Min = 60L*1000L*1000L*1000L;
Defines the multiplication factor to convert a minute count to a duration value.
C_Sec
int64_t const C_Sec = 1000L*1000L*1000L;
Defines the multiplication factor to convert a second count to a duration value.
C_Msec
int64_t const C_Msec = 1000L*1000L;
Defines the multiplication factor to convert a millisecond count to a duration value.
C_Usec
int64_t const C_Usec = 1000L;
Defines the multiplication factor to convert a microsecond count to a duration value.
C_Nsec
int64_t const C_Nsec = 1L;
Defines the multiplication factor to convert a nanosecond count to a duration value.
Functions
init
Init functions
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
cDuration dur;
int64_t exp;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
testSlice tests = slice_c_( test,
t_( secs_c( 4851 ),
1*C_Hour + 20*C_Min + 51*C_Sec ),
t_( mins_c( 132 ),
2*C_Hour + 12*C_Min ),
t_( usecs_c( 40851123456L ),
11*C_Hour + 20*C_Min + 51*C_Sec + 123456*C_Usec )
);
for_each_c_( test const*, t, tests )
{
bool res = ( t->dur._v == t->exp );
tap_descf_c( res, "test: %"PRIi64, index_of_c_( tests, t ) );
}
return finish_tap_c_();
}
duration_c
cDuration duration_c( int64_t h, int64_t m, int64_t s, int64_t n );
Initialise a duration with hour, minute, second and nanosecond.
weeks_c
cDuration weeks_c( int64_t weeks );
Creates a duration from a week count.
days_c
cDuration days_c( int64_t days );
Creates a duration from a day count.
hours_c
cDuration hours_c( int64_t hours );
Creates a duration from a hour count.
mins_c
cDuration mins_c( int64_t minutes );
Creates a duration from a minute count.
secs_c
cDuration secs_c( int64_t seconds );
Creates a duration from a second count.
msecs_c
cDuration msecs_c( int64_t milliseconds );
Creates a duration from a millisecond count.
usecs_c
cDuration usecs_c( int64_t microseconds );
Creates a duration from a microsecond count.
nsecs_c
cDuration nsecs_c( int64_t nanoseconds );
Creates a duration from a nanosecond count.
null_duration_c
cDuration null_duration_c( void );
Returns a null duration, null durations are invalid.
from
duration_from_hmsn_c
cDuration duration_from_hmsn_c( cHmsn hmsn );
Create a cDuration value from a cHmsn value. An invalid cHmsn value leads to an invalid cDuration value.
Unresolved directive in cDuration.adoc - include::../../../test/clingo/time/cDuration/duration_from_hmsn.c[]
hmsn_from_duration_c
cHmsn hmsn_from_duration_c( cDuration dur );
Creates a cHmsn value from a cDuration value. An invalid cDuration value leads to an invalid cHmsn value.
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
cDuration dur;
cHmsn exp;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
testSlice tests = slice_c_( test,
t_( nsecs_c( 1*C_Hour + 12*C_Min + 53*C_Sec + 654321*C_Usec ),
hmsn_c( 1, 12, 53, 654321000 ) ),
t_( nsecs_c( 34*C_Min + 47*C_Sec ),
hms_c( 0, 34, 47 ) ),
t_( nsecs_c( -2*C_Hour - 34*C_Min - 56*C_Sec - 987654321*C_Nsec ),
hmsn_c( -2, -34, -56, -987654321 ) )
);
for_each_c_( test const*, t, tests )
{
cHmsn x = hmsn_from_duration_c( t->dur );
bool res = eq_c( cmp_hmsn_c( x, t->exp ) );
tap_descf_c( res, "%d:%d:%d.%d", x.hour, x.min, x.sec, x.nsec );
}
return finish_tap_c_();
}
conv
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
int main( void )
{
init_tap_c_();
// 32 mins == 1920 secs
cDuration shortDur = duration_c( 0, 32, 15, 123456789 );
expect_c_( as_mins_c( shortDur ) == 32 );
expect_c_( as_secs_c( shortDur ) == 1935 );
expect_c_( as_msecs_c( shortDur ) == 1935123L );
expect_c_( as_usecs_c( shortDur ) == 1935123456L );
expect_c_( as_nsecs_c( shortDur ) == 1935123456789L );
return finish_tap_c_();
}
as_weeks_c
int64_t as_weeks_c( cDuration duration );
Returns the duration as integer week count.
as_days_c
int64_t as_days_c( cDuration duration );
Returns the duration as an integer day count.
as_hours_c
int64_t as_hours_c( cDuration duration );
Returns the duration as an integer hour count.
as_mins_c
int64_t as_mins_c( cDuration duration );
Returns the duration as an integer minute count.
as_secs_c
int64_t as_secs_c( cDuration duration );
Returns the duration as an integer second count.
as_msecs_c
int64_t as_msecs_c( cDuration duration );
Returns the duration as an integer millisecond count.
as_usecs_c
int64_t as_usecs_c( cDuration duration );
Returns the duration as an integer microsecond count.
as_nsecs_c
int64_t as_nsecs_c( cDuration duration );
Returns the duration as an integer nanosecond count.
to_time_unit_c
int64_t to_time_unit_c( int64_t val, int64_t from, int64_t to );
Converts a duration value from one multiplication factor to another.
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
int main( void )
{
init_tap_c_();
expect_c_( to_time_unit_c( 3, C_Min, C_Sec ) == 180 );
expect_c_( to_time_unit_c( 62, C_Min, C_Hour ) == 1 );
return finish_tap_c_();
}
overall
add_duration_c
cDuration add_duration_c( cDuration a, cDuration b );
Adds both duration value to one single value.
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
cDuration a;
cDuration b;
cDuration exp;
char const* desc;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
testSlice tests = slice_c_( test,
// days
t_( duration_c( 22*24, 14, 3, 0 ), days_c( 2 ),
duration_c( 24*24, 14, 3, 0 ), "add 2d" ),
t_( duration_c( 22*24, 14, 3, 0 ), days_c( -20 ),
duration_c( 2*24, 14, 3, 0 ), "add -20d" ),
// hours
t_( duration_c( 126, 4, 24, 0 ), hours_c( 1 ),
duration_c( 127, 4, 24, 0 ), "add 1h" ),
t_( duration_c( 126, 4, 24, 0 ), hours_c( -5 ),
duration_c( 121, 4, 24, 0 ), "add -5h" ),
t_( duration_c( 0, 4, 24, 0 ), hours_c( -10 ),
duration_c( -9, -55, -36, 0 ), "add -10h" ),
// mins
t_( duration_c( 13, 5, 14, 0 ), mins_c( 50 ),
duration_c( 13, 55, 14, 0 ), "add 50m" ),
t_( duration_c( 13, 5, 14, 0 ), mins_c( -6 ),
duration_c( 12, 59, 14, 0 ), "add -6m" ),
t_( duration_c( 1, 5, 14, 0 ), mins_c( -120 ),
duration_c( 0, -54, -46, 0 ), "add -120m" ),
// secs
t_( duration_c( 1, 4, 24, 0 ), secs_c( 3 ),
duration_c( 1, 4, 27, 0 ), "add 3s" ),
t_( duration_c( 1, 0, 24, 0 ), secs_c( -30 ),
duration_c( 0, 59, 54, 0 ), "add -30s" )
);
for_each_c_( test const*, t, tests )
{
cDuration dur = add_duration_c( t->a, t->b );
tap_desc_c( eq_duration_c( dur, t->exp ), t->desc );
}
return finish_tap_c_();
}
between_durations_c
cDuration between_durations_c( cDuration a, cDuration b );
Returns the duration between two duration values.
cmp_duration_c
int cmp_duration_c( cDuration a, cDuration b );
Compares two duration and returns the three possible results:
- <0
-
if a is shorter as b
- 0
-
if both dates are equal
- >0
-
if a is longer as b
duration_is_valid_c
bool duration_is_valid_c( cDuration dur );
Returns true if the duration is valid, otherwise false.
eq_duration_c
bool eq_duration_c( cDuration a, cDuration b );
Returns true if both durations are equal, otherwise false.
invert_duration_c
cDuration invert_duration_c( cDuration dur );
Inverts the duration value, from positive to negative or vice versa.
truncate_duration_c
#define truncate_duration_c_( Dur, Fac ) \
trauncate_duration_c( (Dur), (Fac), ref_c_( cDuration, null_duration_c() ) )
cDuration truncate_duration_c( cDuration dur,
int64_t fac,
cDuration tail[static 1] );
Returns the result of rounding dur toward zero to a multiple of fac, the truncated part of the duration can be stored in tail. If fac ⇐ 0, returns the function dur unchanged.
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
cDuration dur;
int64_t fac;
cDuration exp;
cDuration expTail;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
cDuration dur = duration_c( 1, 15, 30, 918273645 );
testSlice tests = slice_c_( test,
t_( dur, C_Nsec, dur,
nsecs_c( 0 ) ),
t_( dur, C_Usec, duration_c( 1, 15, 30, 918273000 ),
nsecs_c( 645 ) ),
t_( dur, C_Msec, duration_c( 1, 15, 30, 918000000 ),
nsecs_c( 273645 ) ),
t_( dur, C_Sec, duration_c( 1, 15, 30, 0 ),
nsecs_c( 918273645 ) ),
t_( dur, 2*C_Sec, duration_c( 1, 15, 30, 0 ),
nsecs_c( 918273645 ) ),
t_( dur, C_Min, duration_c( 1, 15, 0, 0 ),
duration_c( 0, 0, 30, 918273645 ) ),
t_( dur, 10*C_Min, duration_c( 1, 10, 0, 0 ),
duration_c( 0, 5, 30, 918273645 ) ),
t_( dur, C_Hour, duration_c( 1, 0, 0, 0 ),
duration_c( 0, 15, 30, 918273645 ) )
);
for_each_c_( test const*, t, tests )
{
cDuration tail;
cDuration dur = truncate_duration_c( t->dur, t->fac, &tail );
bool res = eq_duration_c( dur, t->exp ) and
eq_duration_c( tail, t->expTail );
tap_descf_c( res, "" );
}
return finish_tap_c_();
}
io
The functions read_duration_c and write_duration_c are using the following format:
w/W |
Optional week value with a w or W after the value |
5w or 5W |
ww/WW |
Week value with a w or W after the value |
5w or 0W |
d/D |
Optional week value with a d or D after the value |
6d or 6D |
dd/DD |
Week value with a d or D after the value |
0d or 7D |
h/H |
Optional week value with a h or H after the value |
12h or 12H |
hh/HH |
Week value with a h or H after the value |
12h or 0H |
m/M |
Optional minute value with a m or M after the value |
|
mm/MM |
Minute value with a m or M after the value |
|
s/S |
Optional second value with a s or S after the value |
|
ss/SS |
Second value with a s or S after the value |
|
i/I |
Optional millisecond value with ms or MS after the value |
|
ii/II |
Millisecond value with ms or MS after the value |
|
u/U |
Optional microsecond value with µs or µS after the value |
|
uu/UU |
Microsecond value with µs or µS after the value |
|
n/N |
Optional nanosecond value with ns or NS after the value |
|
nn/NN |
Nanosecond value with ns or NS after the value |
|
*U |
Determines, based on the value, the right format SS.N, II.N, UU.N or NN |
|
*l |
Determines, based on the value, the right format ss.n, ii.n, uu.n or nn |
|
(space) |
Will insert a space to the output |
read_duration_c
#define read_duration_c( Sca, Dur ) \
read_duration_c( (Sca), (Dur), "" )
bool read_duration_c( cScanner sca[static 1],
cDuration dur[static 1],
char const fmt[static 1] );
Reads a cDuration value from a text with a scanner. The
#include "clingo/io/read.h"
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
char const* str;
char const* fmt;
cDuration exp;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
testSlice tests = slice_c_( test,
t_( "3d3m3.456789ms", "", duration_c( 72, 3, 0, 3456789 ) ),
t_( "3d3m0.3456789s", "", duration_c( 72, 3, 0, 345678900 ) ),
t_( "0W3D0H3M0.3S", "WDHM*U", duration_c( 72, 3, 0, 300000000 ) ),
t_( "0W 3D 0H 3M 0.3S", "WW DD HH MM *U", duration_c( 72, 3, 0, 300000000 ) ),
t_( "72h3m3.5s", "hm", duration_c( 72, 3, 0, 0 ) ),
t_( "3s", "", secs_c( 3 ) )
);
for_each_c_( test const*, t, tests )
{
cScanner* sca = &cstr_scanner_c_( t->str );
cDuration dur;
bool res = read_duration_c( sca, &dur, t->fmt );
res &= eq_c( cmp_duration_c( dur, t->exp ) );
cRecorder* rec = &recorder_c_( 32 );
write_duration_c_( rec, dur );
tap_descf_c( res, "%s -> %s", t->fmt, turn_into_cstr_c( rec ) );
}
return finish_tap_c_();
}
write_duration_c
#define write_duration_c_( Rec, Dur ) \
write_duration_c( (Rec), (Dur), "" )
bool write_duration_c( cRecorder rec[static 1],
cDuration dur,
char const fmt[static 1] );
Writes a cDuration value into the reocorder. The function will use "wdhm*l" as default format.
#include "clingo/lang/expect.h"
#include "clingo/time/cDuration.h"
TEMP_SLICE_C_(
test,
{
cDuration dur;
char const* fmt;
char const* exp;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
cDuration dur = duration_c( 72, 3, 0, 3456789 );
cDuration max = C_MaxDuration;
testSlice tests = slice_c_( test,
t_( dur, "", "3d3m3.456789ms" ),
t_( dur, "WWDDHHMMSS.I", "0W3D0H3M0.003S" ),
t_( dur, "WW DD HH MM SS.I", "0W 3D 0H 3M 0.003S" ),
t_( dur, "hmss.n", "72h3m0.003456789s" ),
t_( dur, "ww", "0w" ),
t_( dur, "w", "" ),
t_( max, "wwddhhmmss.n", "15250w1d23h47m16.854775807s" ),
t_( invert_duration_c( max ), "", "-15250w1d23h47m16.854775807s" ),
t_( max, "w", "15250w" ),
t_( max, "d", "106751d" ),
t_( max, "h", "2562047h" ),
t_( max, "m", "153722867m" ),
t_( max, "s", "9223372036s" ),
t_( max, "ss.i", "9223372036.854s" ),
t_( max, "ss.u", "9223372036.854775s" ),
t_( max, "ss.n", "9223372036.854775807s" ),
t_( max, "*U", "9223372036.854775807S" )
);
for_each_c_( test const*, t, tests )
{
cRecorder* rec = &recorder_c_( 64 );
bool res = write_duration_c( rec, t->dur, t->fmt );
res &= recorded_is_c( rec, t->exp );
tap_descf_c( res, "'%s' -> '%s'", t->fmt, turn_into_cstr_c( rec ) );
}
return finish_tap_c_();
}