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

Example
#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.

Example
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.

Example
#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

Example
#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.

Example
#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.

Example
#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.

Example
#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:

Table 1. 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

Example
#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.

Example
#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_();
}