Time Variable Conversion
Some query functions, such as TIMERANGE, require the date and time to be entered in a specific format that does not have some key properties. Current restrictions to this are:
- local time offset to UTC,
- inability to specifically set daylight saving time(DST),
- no standardised format.
Note the following for the time values and variables:
- Runtime values/alarms can be created with an accuracy of up to nanoseconds.
- Historical databases retain the correct sequence, but only store up to milliseconds, i.e. they discard the parts with higher accuracy.
- The comparison of WinCC OA time variables only takes milliseconds into account. WinCC OA time variables that only differ in the microsecond or nanosecond range would be considered the same by the built-in comparison methods.
Date-Time formats in WinCC OA
Currently, there are multiple ways to convert Date-Time from a human-readable string format to a time variable.
scanTimeUTC()
Determines the local time from a UTC time string:
- UTC date-time string in the format
YYYY.MM.DD HH:MM:SS.mmm
- "ISO" format:
YYYY-MM-DDTHH:MM:SS.mmm
httpParseDate()
Allows parsing an RFC-2616 conform date string, e.g. from header "If-Modified-Since".
Sun, 06 Nov 1994 08:49:37 GMT
; RFC 822, updated by RFC 1123Sunday, 06-Nov-94 08:49:37 GMT
; RFC 850, obsoleted by RFC 1036Sun Nov 6 08:49:37 1994
; ANSI C's asctime() format
Conversion of WinCC OA TextVar
to TimeVar
variables.
Documented format:
- Local date-time string in the format
YYYY.MM.DD HH:MM:SS.mmm
Additional possible formats:
- Local date-time string in the format
YY.MM.DD HH:MM:SS.mmm
- Local time string in the format
HH:MM:SS.mmm
- Local date-time string in the format
YYYY.MM.DD HH:MM:SS.mmm acount
- If date is missing day parameter it is set to 1.
Additional rules:
- if month > 12 then month = 12
- if month < 1 then month = 1
- if day > 31 then day = 31
- if day < 1 then day = 1
Examples of additional conversion rules:
Input[In local time zone] | Output[In local time zone] |
---|---|
21:30:01.010 |
<current date> 21:30:01.010 e.g. 2023.02.17 21:30:01.010 |
21:30:01 |
<current date> 21:30:01.000 e.g. 2023.02.17 21:30:01.000 |
21:30 |
<current date> 21:30:00.000 e.g. 2023.02.17 21:30:00.000 |
21: |
<current date> 21:00:00.000 e.g. 2023.02.17 21:00:00.000 |
21 |
1970.1.1 21:00:00.000 |
2023.12.26 |
2023.12.26 00:00:00.000 |
2023.12 |
2023.12.01 00:<random-Memory Access Violation>:00.000 |
2023.12. |
2023.12.01 00:00:00.000 |
2023. |
2023.01.01 00:00:00.000 |
2023.12.01 21 |
2023.12.01 21:00:00.00 |
abcdef |
1970.01.01 01:00:00.000 |
abc.def |
2000.01.01 00:00:00.000 |
abc:def |
<current date> 01:00:00.000 |
abc def |
1970.01.01 01:00:00.000 |
Date-Time overflow processing | |
2038.99.99 25:61:61 |
2038.12.31 23:59:59.000 |
2023.01.99 00:00:00 |
2023.01.31 00:00:00.000 |
2023.02.99 00:00:00 |
2023.03.03 00:00:00.000 |
Handling bad input format
scanTimeUTC()
There is an entry in the error section that
says "For example: no/incorrect parameters, incorrect format", but when the wrong input is entered, the getLastError
function does not return any error. The returned time will have the value 1970.01.01 00:00:00.000 UTC
.
DateTime overflow:
- Input in ISO format will result in
1970.01.01 00:00:00.000 UTC
. - Input in non ISO format can correctly handle overflow in fields:
DD HH:MM:SS.mmm
makeTime()
Uses system C mktime
function which handles overflow correction correctly e.g.
makeTime(2023,8,32,13,50)
creates the time 2023.09.01 13:50:00.000
.
Casting string
variable to time
variable.
Uses an automatic correction (clamping to max, min value) or will return 1970.01.01 01:00:00.000
value. No information
is provided to the user.
ISO8601 Requirements
The user should be able to enter data in a human-readable time format according to ISO8601. At the same time, backward compatibility with
legacy date and time formatting options should be maintained. Incorrect date and time format can be detected. These requirements apply to
SQL queries (e.g., TIMERANGE
) and to the conversion of WinCC OA
TextVar
to TimeVar
variables.
Allowed formats
ISO8601 - with extended time format
- Standard format:
yyyy-MM-ddThh:mm:ss.sss[Z|[+|-]hh:mm]
- Extended format for
ExtTimeVar
:
where:yyyy-MM-ddThh:mm:ss.sss[Z|[+|-]hh:mm] aCount
YYYY = four-digit year MM = two-digit month (01=January, etc.) DD = two-digit day of month (01 through 31) hh = two digits of hour (00 through 23) (am/pm NOT allowed) mm = two digits of minute (00 through 59) ss = two digits of second (00 through 59) s = one or more digits representing a decimal fraction of a second TZD = time zone designator (Z or +hh:mm or -hh:mm) aCount - alert count
Examples of valid inputs: Date and time in:
2023-02-15T06:48:32.500+00:00
UTC:2023-02-15T06:48:32.500Z
Legacy date-time formats
- UTC date-time string in the format "YYYY.MM.DD HH:MM:SS.mmm"
- UTC date-time string in the format "YY.MM.DD HH:MM:SS.mmm"
- UTC time string in the format "HH:MM:SS.mmm"
- UTC date-time string in the format "YYYY.MM.DD HH:MM:SS.mmm aCount"
Expected behavior for legacy string conversion to TimeVar
:
Input[In local time zone] | Output[In local time zone] | Valid | Warning/Error |
---|---|---|---|
2023.12.01 21:30:01.001 |
2023.12.01 21:30:01.001 |
Yes | No |
2023.12.01 21:30:01.001<whitespace> |
2023.12.01 21:30:01.001 |
Yes | No |
2023.12.01 21:30:01 |
2023.12.01 21:30:01.000 |
Yes | No |
2023.12.01 21:30 |
2023.12.01 21:30:00.000 |
Yes | No |
2023.12.01 21: |
2023.12.01 21:00:00.000 |
No | Error |
2023.12.01 21 |
2023.12.01 21:00:00.00 |
No | Error |
2023.12 21:30:01.001 |
2023.12.01 21:30:01.001 |
No | Error |
2023.12 21:30:01.001 |
2023.12.01 21:30:01.001 |
No | Error |
2023. 21:30:01.001 |
2023.01.01 21:30:01.001 |
No | Error |
21:30:01.010 |
<current date> 21:30:01.010 e.g.
2023.02.17 21:30:01.010 |
No | Warning |
21:30:01 |
<current date> 21:30:01.000 e.g.
2023.02.17 21:30:01.000 |
No | Warning |
21:30 |
<current date> 21:30:00.000 e.g.
2023.02.17 21:30:00.000 |
No | Warning |
21: |
<current date> 21:00:00.000 e.g.
2023.02.17 21:00:00.000 |
No | Error |
21 |
1970.1.1 21:00:00.000 |
No | Error |
2023.12.26 |
2023.12.26 00:00:00.000 |
No | Warning |
2023.12 |
2023.12.01 00:00:00.000 |
No | Error |
2023.12. |
2023.12.01 00:00:00.000 |
No | Error |
2023. |
2023.01.01 00:00:00.000 |
No | Error |
abcdef |
1970.01.01 01:00:00.000 |
No | Error |
abc.def |
1970.01.01 01:00:00.000 |
No | Error |
abc:def |
1970.01.01 01:00:00.000 |
No | Error |
abc def |
1970.01.01 01:00:00.000 |
No | Error |
Date-Time overflow processing | |||
2038.99.99 25:61:61 |
2038.12.31 23:59:59.000 |
No | Error |
2023.01.99 00:00:00 |
2023.01.31 00:00:00.000 |
No | Error |
2023.02.99 00:00:00 |
2023.02.28 00:00:00.000 |
No | Error |
Expected behavior for legacy string conversion to ExtTimeVar
:
Input[In local time zone] | Output[In local time zone] | Valid | Warning/Error |
---|---|---|---|
2023.12.01 21:30:01.001 125 |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001 | 125 |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001 (125) |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001|125 |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001(125) |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001 blaa125blaa |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01.001blaa125blaa |
2023.12.01 21:30:01.001 count: 125 |
Yes | No |
2023.12.01 21:30:01 125 |
2023.12.01 21:30:01.000 count: 125 |
Yes | No |
2023.12.01 21:30:01 |125 |
2023.12.01 21:30:01.000 count: 125 |
Yes | No |
2023.12.01 21:30 125 |
2023.12.01 21:30:00.000 count: 125 |
Yes | No |
2023.12.01 21:30 |125 |
2023.12.01 21:30:00.000 count: 125 |
Yes | No |
2023.12.01 21: 125 |
2023.12.01 21:00:00.000 count: 125 |
No | Error |
2023.12.01 21 125 |
2023.12.01 21:00:00.00 count: 0 |
No | Error |
2023.12 21:30:01.001 125 |
2023.12.01 21:30:01.001 count: 125 |
No | Error |
2023.12 21:30:01.001 125 |
2023.12.01 21:30:01.001 count: 125 |
No | Error |
2023. 21:30:01.001 125 |
2023.01.01 21:30:01.001 count: 125 |
No | Error |
21:30:01.010 125 |
<current date> 21:30:01.010 count:
125 |
No | Warning |
21:30:01 125 |
<current date> 21:30:01.000 count:
125 |
No | Warning |
21:30 125 |
<current date> 21:30:00.000 count:
125 |
No | Warning |
21: 125 |
<current date> 21:00:00.000 count: 0 |
No | Error |
21 125 |
1970.1.1 21:00:00.000 count: 0 |
No | Error |
21:30:00 -125 |
2023.12.01 21:30:00.000 count: 125 |
No | Error |
21:30:00 ABCD |
2023.12.01 21:30:00.000 count: 0 |
No | Error |
Handling bad input format
TIMERANGE
: If a user enters the date and time in SQL queries in the wrong format, the query is evaluated as invalid, e.g.
dpQuery returns -1, which indicates an error. The error can be retrieved by a subsequent call to getLastError()
.
In the case of converting a string variable to a time variable, handling the wrong input format will produce warning/error message. To
catch these types of errors, you can use the function setThrowErrorAsException()
. This function enables the current
thread to throw an exception in case of an error that can be caught using a try/catch block. When an error occurs after calling
setThrowErrorAsException()
, it will be thrown as an exception, which can then be caught and handled
appropriately.
setThrowErrorAsException();
time t;
try
{
t = (time)"2022-99-99T01:03:00.567";
}catch
{
dyn_errClass err = getLastException();
DebugN(err);
}
Output:
WCCOActrl2:[dyn_errClass 1 items
WCCOActrl2:WCCOActrl (2), 2023.03.03 13:40:00.166, CTRL, WARNING, 51, Parameter incorrect, TimeVar, operator=, ISO format >error. Must be: YYYY-MM-DDTHH:MM:SS.mmm
WCCOActrl2: Stacktrace:
WCCOActrl2: 1: void main() at tests\TestFile.ctl:61
WCCOActrl2:]
Example of log messages:
WCCOActrl (2), 2023.02.16 15:40:11.189, IMPL, WARNING, 50, TimeVar, operator=, DateTime format error. Must be: YYYY.MM.DD HH:MM[:SS.mmm]
WCCOActrl (2), 2023.02.16 15:40:11.189, IMPL, WARNING, 50, TimeVar, operator=, ISO format error. Must be: YYYY-MM-DDTHH:MM:SS.mmm
WCCOActrl (2), 2023.02.16 15:40:11.189, IMPL, WARNING, 50, TimeVar, operator=, aCount format error. Must be: YYYY.MM.DD HH:MM[:SS.mmm] aCount