Overview

The following functions help to create and use STEP data and time descriptions. If you are just creating one or two dates, the defaults of the "make" functions should be fine for your purposes, but if you are creating many sequential timestamps, there are extra fields to pass in data for reusing date and timezone objects.

For input and output, the ISO 8601 string format for dates and times is used. An example of an ISO 8601 strings with dates, times, and timezone are shown below.

   2006-11-16			date only
   2006-11-16T17:05:17		date and time
   2006-11-16T17:05:17.1234	date and time to milliseconds
   2006-11-16T17:05:17-05:00	date, time, and offset from UTC

All definitions are in the stix_date.h header file.

stix_date_parse()

int stix_date_parse(
	stp_date * dc,
	int &as_year,
	int &as_month,
	int &as_day
	);

The stix_date_parse() function collects the individual date component values from a STEP date object. When a value is omitted, the parameter will be set to ROSE_NULL_INT. This function returns zero on success or non-zero if the date object does not exist.

This function understands all of the different STEP date subtypes and will convert them into calendar dates if necessary.

#44=CALENDAR_DATE(1972,30,6);
==> returns Y:1972 M:06 D:30

#60=YEAR_MONTH(1972,6);
==> returns Y:1972 M:06 D:NULL

#64=DATE(1972);
==> returns Y:1972 M:NULL D:NULL

#74=ORDINAL_DATE(1972,182);
==> returns Y:1972 M:06 D:30 (converted)

#84=WEEK_OF_YEAR_AND_DAY_DATE(2020,1,2);
==> returns Y:2019 M:12 D:31 (converted, 2020-W01-02 is 2019-12-31)

stix_datetime_cmp()

int stix_datetime_cmp(
	stp_date_and_time * dt_1,
	stp_date_and_time * dt_2
	);

The stix_datetime_cmp() function compares two STEP time and date objects, following the pattern of strcmp. Return value is positive if dt1 is later in time, negative if dt1 is earlier and zero if they are the same. If a date and time contains errors, it is treated as the time 0000-00-00T00:00:00Z for comparison.

stix_datetime_diff()

double stix_datetime_diff(
	stp_date_and_time * dt_end,
	stp_date_and_time * dt_begin,
        RoseUnit u = roseunit_sec
	);

The stix_datetime_diff() function computes the time difference between two STEP time and date objects. The return value is positive if the first argument is later in time, negative if it is earlier and zero if they are the same. The function returns ROSE_NULL_REAL if either of the objects date and time contain errors.

By default, the time difference is measured in seconds, but you can pass in an optional RoseUnit to select a different unit.

stix_datetime_format()

const char * stix_datetime_format(
	RoseStringObject &retstr,
	stp_date_and_time * dt
	);

The stix_datetime_format() function creates an ISO 8601 time and date string from a STEP date and time object. The string is stored in the RoseStringObject that is passed in and the function returns the result as a const char* for immediate use. See rose_datetime_format() for more information about ISO 8601 strings.

stix_datetime_parse()

int stix_datetime_parse(
	stp_date_and_time * dt,
	int &as_year,
	int &as_month,
	int &as_day,
	int &as_hour,
	int &as_minute,
	double &as_sec,
	int &tz_hrs,
	int &tz_mins
	);

The stix_datetime_parse() function collects the individual time and date component values from a STEP date and time object. When a value is omitted, the parameter will be set to ROSE_NULL_INT (or ROSE_NULL_REAL for the seconds). This function follows the pattern of of rose_datetime_parse() and returns zero on success or non-zero if the date and time object does not exist.

The function uses stix_date_parse() to process the various STEP date representations and convert values into calendar dates if necessary.

stix_make_date()

stp_date * stix_make_date(
	RoseDesign * d,
	time_t as_time,
 	stp_date * last_date = 0
	);

stp_date * stix_make_date(
	RoseDesign * d,
	const char * as_timestr,
 	stp_date * last_date = 0
	);

stp_date * stix_make_date(
	RoseDesign * d,
	int as_year,   // four digit
	int as_month,  // 1-12
	int as_day,    // 1-31
	stp_date * last_date = 0
	);

The stix_make_date() function constructs a STEP date object from the given time_t value, string representation, or individual values. The function expects a string value in in ISO 8601 format (for example "2020-06-30") and any time portion is ignored. When passing individual values, the function expects a four-digit year, month from 1-12, and day from 1-31. The function returns null if the input time value is not valid.

If you make many calls to these functions, you can pass in an existing date object in the optional "last" parameters. The function will reuse the object if the date has not changed.

The function returns a calendar_date when given complete information. When the input values contain partial data, like the strings "2019-11" and "2019", or ROSE_NULL_INT for individual values, the function returns other date subtypes.

stp_date * dt;

dt = stix_make_date(d, "1972-06-30");
==> returns CALENDAR_DATE(1972,30,6);

dt = stix_make_date(d, "1972-06"); 
==> returns YEAR_MONTH(1972,6);

dt = stix_make_date(d, "1972"); 
==> returns DATE(1972);


/* individual components */
dt = stix_make_date(d, 1972, 06, 30);
==> returns CALENDAR_DATE(1972,30,6);

dt = stix_make_date(d, 1972, 06, ROSE_NULL_INT); 
==> returns YEAR_MONTH(1972,6);

dt = stix_make_date(d, 1972, ROSE_NULL_INT, ROSE_NULL_INT); 
==> returns DATE(1972);

/* June 30, 1972 is the 182nd day of the year */
dt = stix_make_date(d, 1972, ROSE_NULL_INT, 182); 
==> returns ORDINAL_DATE(1972,182);

stix_make_date_now()

stp_date * stix_make_date_now(
	RoseDesign * d,
 	stp_date * last_date = 0
	);

The stix_make_date_now() function constructs a STEP calendar date object for the current moment in time using stix_make_date(). The function returns null if the current time can not be determined.

If you make many calls to these functions, you can pass in an existing date object in the optional "last" parameters. The function will reuse the object if the date has not changed.

stix_make_datetime()

// Second accuracy
stp_date_and_time * stix_make_datetime(
	RoseDesign * d,
	time_t as_time,
	stp_date_and_time * last_date = 0
	);

// String description
stp_date_and_time * stix_make_datetime(
	RoseDesign * d,
	const char * as_time,
	stp_date_and_time * last_date = 0
	);

// Individual components
stp_date_and_time * stix_make_datetime(
	RoseDesign * d,
	int as_year,   // four digit
	int as_month,  // 1-12
	int as_day,    // 1-31
	int as_hour,   // 0-23
	int as_minute, // 0-59
	double as_sec, // >=0 and <60
	stp_date_and_time * last_date = 0
	);

stp_date_and_time * stix_make_datetime(
	RoseDesign * d,
	int as_year,   // four digit
	int as_month,  // 1-12
	int as_day,    // 1-31
	int as_hour,   // 0-23
	int as_minute, // 0-59
	double as_sec, // >=0 and <60
	stp_coordinated_universal_time_offset * tzone
	);

The stix_make_datetime() function constructs a STEP data_and_time object with a calendar_date and local_time from the given time_t value, individual components, or ISO 8601 string representation. The function returns null if the input time value is not valid.

If you make many calls to these functions, you can pass in an existing date_and_time object in the optional "last" parameter. The function will reuse objects that have not changed.

When passing individual values, the function expects a four-digit year, month from 1-12, and day from 1-31. The hour should be 0-23, minute from 0-59, and seconds from zero to less than 60. The time zone will be the value in the "last" parameter or the local timezone if none is provided.

When passing a time_t, the function will decode it to the local time. The time zone will always be the local timezone, and the value in the "last" parameter will be reused if it matches.

When passing an ISO 8601 string, the function will use the time zone offset encoded in the string. If the string contains a time with no offset, the local time zone will be used. If the string contains no time component, the function will use Midnight UTC. The time zone object in the "last" parameter will be reused if it matches.

The time_t value can represent values down to individual seconds. Use the individual components version with a decimal value for the seconds or stix_make_datetime_now_ms() for sub-second resolution. ISO 8601 strings can contain values to any resolution. STEP allows the minute and second values to be omitted. Pass ROSE_NULL_INT to "as_minute" and ROSE_NULL_REAL to "as_sec" to omit them. If all time components are null, the function will use Midnight UTC as the time.

RoseDesign * d = ...

stp_date_and_time * tstart;
stp_date_and_time * tstop;

// create new objects for everything
tstart = stix_make_datetime(d, time(NULL));
[ ... ]
// reuse what we can from date and timezone
tstop = stix_make_datetime(d, time(NULL), tstart);

In the example above, we create time objects for the current moment in time, so stix_make_datetime_now() could alternatively be used.

// create new objects for everything
tstart = stix_make_datetime_now(d);
[ ... ]
// reuse what we can from date and timezone
tstop = stix_make_datetime_now(d, tstart);

The functions also accept ISO 8601 strings with their range of options. As above, these functions will reuse existing objects when possible if you provide them.

// create new objects for everything
stp_date_and_time * dt;

// Time in the local timezone of the computer
dt = stix_make_datetime(d, "2020-08-07T10:26:24");

// Time in UTC
dt = stix_make_datetime(d, "2019-06-30T14:20:30Z");

// Time in UTC with fractional seconds, reusing what you can.
// Using full stop (.) decimal separator allowed by ISO 8601.
// Full stop appears to be common case, particularly with MTConnect.
dt = stix_make_datetime(d, "2019-06-30T14:20:30.55Z", dt);

// Time in UTC with fractional seconds, using comma (,) decimal
// separator allowed by ISO 8601.
dt = stix_make_datetime(d, "2019-06-30T14:20:30,65Z", dt);

// Timezones eight hours behind UTC (western USA) and five
// hours ahead (central Asia)
dt = stix_make_datetime(d, "2020-08-06T15:21:03-08:00");
dt = stix_make_datetime(d, "2020-08-06T16:21:03+05:00");

// The ISO 8601 "basic form" of the above times is also recognized.
// This omits the "-" and ":" field separators.
dt = stix_make_datetime(d, "20190630T142030Z");
dt = stix_make_datetime(d, "20190630T142030.55Z");
dt = stix_make_datetime(d, "20190630T142030,65Z");
dt = stix_make_datetime(d, "20200806T152103-0800");
dt = stix_make_datetime(d, "20200806T162103+0500");

stix_make_datetime_now()

stp_date_and_time * stix_make_datetime_now(
	RoseDesign * d,
 	stp_date_and_time * last_date = 0
	);

The stix_make_datetime_now() function constructs a STEP data_and_time object from the current time, with precision to the current second, using stix_make_datetime(). Use stix_make_datetime_now_ms() if you need precision to the millisecond.

When no "last_date" is given, the function will attempt to determine the local time zone offset. The function returns null if the input time value is not valid.

stix_make_datetime_now_ms()

stp_date_and_time * stix_make_datetime_now_ms(
	RoseDesign * d,
 	stp_date_and_time * last_date = 0
	);

The stix_make_datetime_now_ms() function constructs a STEP data_and_time object from the current time, with precision to the current millisecond, using stix_make_datetime().

When no "last_date" is given, the function will attempt to determine the local time zone offset. The function returns null if the input time value is not valid.

stix_make_timezone()

stp_coordinated_universal_time_offset * stix_make_timezone(
	RoseDesign * d,
	int utc_hours = ROSE_NULL_INT, 
	int utc_minutes = ROSE_NULL_INT,
 	stp_coordinated_universal_time_offset * last_utc = 0
	);

stp_coordinated_universal_time_offset * stix_make_timezone(
	RoseDesign * d,
	stp_coordinated_universal_time_offset * last_utc
	);

The stix_make_timezone() function creates a UTC offset object that describes the time zone of a local_time value. The hour and minute values are signed and should be positive for zones to the east of UTC and negative for zones to the west.

If no UTC offset hours or minutes are given, the function will will attempt to determine the local time zone offset. You can pass in an existing timezone object in the optional "last" parameter and the function will reuse the object if the offset has not changed.