In SQL
date, andtimefields are converted to type the eXtremeDB typedatetimefor all operations. The only difference is how they are formatted for output. So, for example adatefielddaycould be incrementedday+5and the result will be of typedate.For an overview see page Date, Time and Datetime Fields
The
date,timeanddatetimetypes are represented internally as integer values. When arithmetic is performed, the result will be of the original type, but the underlying value is used to perform arithmetic. So thedatetimeprecision can be important. The default precision for xSQL is 1, i.e. 1 second. But it can be changed by thesetDateTimePrecision()function. Regardless whether typedateordatetimeis used, seconds (or milliseconds, etc.) will be used in the operation.For example, consider the following operations:
XSQL>select cast('02-02-2013' as date); #1 ------------------------------------------------------------------------------ 02/02/2013 00:00:00 Selected records: 1 XSQL>select cast('02-02-2013' as time); #1 ------------------------------------------------------------------------------ 02/02/2013 00:00:00 Selected records: 1 XSQL>select cast('02-02-2013' as date) + 5; #1 ------------------------------------------------------------------------------ 02/02/2013 00:00:05 Selected records: 1 XSQL>select setDateTimePrecision(1000); #1 ------------------------------------------------------------------------------ 1 Selected records: 1 XSQL>select cast('02-02-2013' as date) + 5; #1 ------------------------------------------------------------------------------ 02/02/2013 00:00:00.005 Selected records: 1
Inserting Date and Time Data
Data can be inserted into date, time and datetime fields by specifying the date and time in a variety of string formats. (Currently on Windows systems, valid date values must have the year specified as greater than
1969. (Note that on Unix-Linux platforms, and in the next release for Windows, thestrptime()function will be used internally which does not have this limitation.)For example consider the following table:
XSQL>create table dt(d date, t time);Date and time values can be inserted with a string formatted "
M/D/Y h:m:s". If the value ofMis greater than 1900, then the string is considered as"Y/M/D h:m:s". For example:XSQL>insert into dt values( '7/10/1970 15:15:15', '23:23:23'); XSQL>insert into dt values( '1970/7/30', '0'); XSQL>select * from dt; d t --------------------------------------------------------------- 07/10/1970 15:15:15 23:23:23 07/30/1970 00:00:00 00:00:00Insert strings can also use the hyphen or dot separators, instead of slashes, for dates. For example:
XSQL>insert into dt(d) values( '6-10-1970'); XSQL>insert into dt(d) values( '1970.7.30'); XSQL>select * from dt; d t --------------------------------------------------------------- 06/10/1970 00:00:00 00:00:00 07/30/1970 00:00:00 00:00:00Another alternative is to use abbreviations (first three letters) for the month with hyphen separators; i.e. a string with format
"D-MON-Y h:m:s". For example:XSQL>insert into dt(d) values( '30-sep-1970'); XSQL>select * from dt; d t --------------------------------------------------------------- 09/30/1970 00:00:00 nullNote that the month integer value
Mmust be a month number starting from 1 for January, and the year valueYcan be 4 digit integer greater than 1900; otherwise, if the value ofYis less than50it is considered as a2000+year, if greater than or equal to50it is considered a1900+year. For example:XSQL>insert into dt(d) values( '30-aug-20'); XSQL>insert into dt(d) values( '30-aug-80'); XSQL>select * from dt; d t --------------------------------------------------------------- 08/30/2020 00:00:00 null 08/30/1980 00:00:00 nullThe hour
hand minutemvalues must be integers less than24and60respectively and secondsscan be expressed as an integer or floating point value, however floating point fractional values are truncated. For example:XSQL>insert into dt(t) values( '23:59:19.6'); XSQL>select * from dt; d t --------------------------------------------------------------- null 23:59:19If a time part is not supplied, the string is considered as a date and the time part is set as zero. If the string could not be successfully parsed as a date, then the time format
"h:m:s"is tried.
Storing and Manipulating High-definition Datetime Data
When using high-definition data, for instance timestamp fields with millisecond granularity, it is recommended to use the
bigintdata type. It is possible to use achar(9)type field to store a timestamp, for examplecreate table DailyQuotesIN (tTime char(9), ...)The eXtremeSQL runtime will implicitly perform the conversion from a
char(9)to aninteger-- no explicit casts of input data are required. However, from the performance standpoint it is preferable to use thebigintdata type:create table DailyQuotesIN (tTime bigint, ...)Using the
bigintdata type you would simply loadtTimedata with the time encoded as an integer value like093515984593000and perform any manipulations with this data directly, including various forms of output. Note however that to extract some part of the field representing a time (for example the hour or minute), standard SQL functions should not be used; i.e. do not use the SQL functionhour()orminute(). Instead use integer division. For example:select tTime / 10000000000 as hour, tTime / 100000000 % 100 as minute, real(tTime % 10000000000) / 100000000 as second from DailyQuotesIN;
Converting Date to Integer
When using variables of type Date it can be useful to convert the Date value to a long integer value representing the number of milliseconds since January 1, 1970, 00:00:00 GMT. This can be done by using the Date method
getTime(). The following code snippet demonstrates how this method might be used (in Java):{ Calendar cal = Calendar.getInstance(); cal.set(2014, 1, 1, 9, 30); cal.set(2014, 12, 30, 16, 00); Date dstart = cal.getTime(); Date dfinish = cal.getTime(); long start = dstart.getTime(); long finish = dfinish.getTime(); System.out.println("Calculating high bids over symbols from time " + start + " to " + finish + ":"); SqlResultSet res = conn.executeQuery("SELECT Symbol, seq_ignore(seq_search(qTime, ?, ?)) as t, seq_max (Bid@t) FROM Quotes", start, finish);Implementation details
Given the embedded nature of the eXtremeDB, the datetime core data type is stored as a 8-byte integer and allows all integer operations such as addition and subtraction. The datetime type is interpreted by applications, and could represent for example the epoch time in seconds, or the time in CPU ticks since the device was turned on, etc., That said, the higher-level eXtremeDB components such as Java and Python wrapper APIs, SQL API and xSQL server assume that the datetime type is interpreted as a UTC timestamp: the UNIX epoch time.
Epoch, by definition, is a point in time that is used as a reference point for measuring time. It doesn’t necessarily have to have a specific meaning. January, 1 1970 known as the Unix epoch time is used by many Unix-like systems and programming languages, such as C/C++, Java, JavaScript, Perl, PHP, Python, etc. The Unix epoch 0 is at 00:00:00 UTC on 1 January 1970, so systems use a negative number to represent any timestamp before that.
Since Unix time increments every second, and as an alternative to using a different data type to represent time with greater precision, the eXtremeDB adds a property to the datetime type called "datetime precision”. The precision property numerically represents the number of ticks per second. The default value for it is 1, which means that the database stores a datetime value as the number of seconds since the epoch (i.e. 00:00:00 UTC 1 January 1970). However the resolution of datetime fields can be changed by an application to a resolution ranging from 1 (to store the number of seconds) to 1000000000 (for the number of nanoseconds).
For example the epoch time for the "2023-07-04 12:00:00 GMT” date is equal to 1688472000. If the
dt_precisionis set to 1000 indicating the milliseconds resolution, the eXtremeDB database would represent it as 1.688.472.000.000The algorithm used by the
SQL INSERToperator is as follows:The date string is parsed into the C language time structure that contains a calendar date and time broken down into its components. The structure contains nine members of type int (in any order), which are:
MemberTypeMeaningtm_secintseconds after the minutetm_minintminutes after the hourtm_hourinthours since midnighttm_mdayintday of the monthtm_monintmonths since Januarytm_yearintyears sincetm_wdayintdays since Sundaytm_ydayintdays since January 1tm_isdstintDaylight Saving TimeThe eXtremeDB sets the
tm_isdstto -1 indicating that the Daylight Saving Time information is not available. The tm structure is then passed to the C runtimemktime()function that converts the time into the UNIX epoch representation in the current time zone (all time zones are defined as offsets from UTC ). Finally the value is multiplied by the "datetime precision”.Conversely, when the SQL engine reconstructs the stored datetime value back into string, the stored value is divided by the set precision, receiving the epoch time in seconds. Then the epoch time is passed into the C runtime
localtime()function that fills out the tm strcuture in the current time zone and the tm structure values are then represented in a form of a formatted string.Even though most systems in the world use Unix time, it has limitations. On some embedded operating systems such as QNX 7.0, the
mktime()function doesn't support dates below 01/01/1970 (i.e. does not work with negative epoch time). In these cases the eXtremeDB makes use of the time-shift technique that essentially up-shifts all dates below the year 1970 to a predefine number of years, then converts the dates through themktime()and then downshifts the value back prior to storing it in the database. Thus the database runtime keeps all dates passed 1970 as theepoch_time * datetime_precisionvalue while dates prior to 1970 are kept as negative numbers. When applications read dates back, the process is reversed. Note that these values could be off from the epoch time by the date light saving time value (usually one hour) because of different daylight saving rules applied in different calendar years. However, the conversion from the input string into the internal storage representation and back into the string is preserved.Furthermore, some applications benefit from interpreting datetime as intervals in seconds/milliseconds/nanoseconds as opposed to absolute dates. In this case the stored 8-byte value would be formatted as hours:minutes:seconds. In order to accommodate these scenarios it is possible to define an interval from 1/1/1970 forward within which the stored datetime translates to time interval. By default the interval value is zero (all dates are viewed as calendar dates). The SQL function
setMaxInterval(n_sec)or the xSQL commandmaxinterval n_secare used to adjust the length of the interval. For examplemaxinterval 86400instructs the xSQL to interpret all dates 24 hours forward and back from the 1/1/1970 as time interval (note that the referenced values could be negative, which is helpful when arithmetic operations over time values are performed)