Skip to content

Commit 565b595

Browse files
authored
Merge pull request #527 from IBM/lee-master
Set timezone to UTC for all storedprocedure timestamps
2 parents ff9470d + 05fd624 commit 565b595

17 files changed

Lines changed: 1231 additions & 617 deletions

File tree

docs/src/pages/Conformance.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ FHIR search modifiers are described at https://www.hl7.org/fhir/R4/search.html#m
8585
|Reference |`:[type]`,`:missing` |exact match search|
8686
|URI |`:below`,`:above`,`:missing` |exact match search|
8787
|Token |`:missing` |exact match search|
88-
|Number |`:missing` |exact match search|
89-
|Date |`:missing` |exact match search|
88+
|Number |`:missing` |implicit range search (see http://hl7.org/fhir/R4/search.html#number)|
89+
|Date |`:missing` |implicit range search (see https://www.hl7.org/fhir/search.html#date)|
9090
|Quantity |`:missing` |implicit range search (see http://hl7.org/fhir/R4/search.html#quantity)|
9191
|Composite |`:missing` |processes each parameter component according to its type|
9292
|Special (near) | none |searches a bounding area according to the value of the `fhirServer/search/useBoundingRadius` property|
@@ -124,16 +124,25 @@ The `eb` and `ap` prefixes are not supported for searches which target values of
124124
If not specified on a query string, the default prefix is `eq`.
125125

126126
### Searching on Date
127-
The FHIR server adheres to the specification except in cases where a time is included in the search query value. When a time is specified, the implementation requires an hour, minute, second, and timezone value. Including these values is consistent with the way in which `instant` and `dateTime` data types are defined at https://www.hl7.org/fhir/R4/datatypes.html#primitive. However, the implementation differs from the description at https://www.hl7.org/fhir/R4/search.html#date, which allows clients to include hours and minutes, but to omit values for seconds and time zone.
127+
The IBM FHIR Server adheres to the specification with two minor exceptions:
128+
* The server supports search query values with fractional seconds; any search query value given with fractional seconds is treated as precise value, whereas search query values without fractional seconds are handled as an implicit range (e.g. `2000-04-30T23:59:00` becomes the range `[2000-04-30T23:59:00, 2000-04-30T23:59:01)`).
129+
* Dates and DateTimes (and query parameter values for date search parameters) which are expressed without timezones are handled as UTC values.
130+
* This differs slightly from the specification which indicates that "Where both search parameters and resource element date times do not have time zones, the servers local time zone should be assumed". However, because both the element values AND search query parameters are handled in the same way, this difference matters only when timezones are specified on one side (resource element or search query parameter) but not the other. For example, a query like `Patient?birthdate=2019-01-01` would match a resource with a value of `2019-01-01`, but would *not* match a resource with a value of `2019-01-01T20:00:00-04:00`.
128131

129-
The IBM FHIR Server stores up to 6 fractional seconds (microsecond granularity) for Instant and DateTime values (when present) and allows clients to search with these as well.
132+
The IBM FHIR Server supports up to 6 fractional seconds (microsecond granularity) for Instant and DateTime values and all extracted parameter values are stored in the database in UTC in order to improve data portability.
130133

131-
Query parameter values without fractional seconds will be handled as an implicit range. For example, a search like `Patient?date=2019-01-01T12:00:00Z` would include resources with the following effectiveDateTime values:
134+
Dates and DateTimes which are expressed without timezones are assumed to be in the local timezone of the application server at the time of parameter extraction.
135+
Similarly, query parameter date values with no timezone are assumed to be in the local time of the server at the time the search is invoked.
136+
To ensure consistency of search results, clients are recommended to include the timezone on all search query values that include a time.
137+
138+
Finally, the server extends the specified capabilities with support for "exact match" semantics on fractional seconds.
139+
140+
Query parameter values without fractional seconds is handled as an implicit range. For example, a search like `Observatoin?date=2019-01-01T12:00:00Z` would return resources with the following effectiveDateTime values:
132141
* 2019-01-01T12:00:00Z
133142
* 2019-01-01T12:00:00.1Z
134143
* 2019-01-01T12:00:00.999999Z
135144

136-
Query parameter values with fractional seconds will be handled with exact match semantics (ignoring precision). For example, a search like `Patient?date=2019-01-01T12:00:00.100Z` would include resources with the following effectiveDateTime values:
145+
Query parameter values with fractional seconds is handled with exact match semantics (ignoring precision). For example, a search like `Patient?birthdate=2019-01-01T12:00:00.1Z` would include resources with the following effectiveDateTime values:
137146
* 2019-01-01T12:00:00.1Z
138147
* 2019-01-01T12:00:00.100Z
139148
* 2019-01-01T12:00:00.100000Z

fhir-core/src/main/java/com/ibm/fhir/core/FHIRUtilities.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import java.sql.Timestamp;
1010
import java.text.SimpleDateFormat;
11-
import java.time.ZoneId;
1211
import java.util.Base64;
1312
import java.util.Date;
1413
import java.util.TimeZone;
@@ -118,7 +117,7 @@ public static boolean isEncoded(String s) {
118117
* @return
119118
*/
120119
public static Timestamp convertToTimestamp(java.time.ZonedDateTime zdt) {
121-
return Timestamp.from(zdt.withZoneSameInstant(ZoneId.of("UTC")).toInstant());
120+
return Timestamp.from(zdt.toInstant());
122121
}
123122

124123

fhir-examples/src/main/resources/json/ibm/basic/BasicDate.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
{
1616
"url": "http://example.org/dateTime",
17-
"valueDateTime": "2018-10-29T17:12:00-04:00"
17+
"valueDateTime": "2019-12-31T20:00:00-04:00"
1818
},
1919
{
2020
"url": "http://example.org/time",

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/JDBCConstants.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
package com.ibm.fhir.persistence.jdbc;
77

88
import java.util.Arrays;
9+
import java.util.Calendar;
910
import java.util.HashMap;
1011
import java.util.List;
1112
import java.util.Map;
13+
import java.util.TimeZone;
1214

1315
import com.ibm.fhir.search.SearchConstants.Modifier;
1416
import com.ibm.fhir.search.SearchConstants.Type;
@@ -64,34 +66,38 @@ public class JDBCConstants {
6466
public static final char COMMA_CHAR = ',';
6567
public static final char QUOTE = '\'';
6668
public static final char PATH_CHAR = '/';
67-
69+
6870
// JDBC Operators
6971
public static final String EQ = " = ";
7072
public static final String LIKE = " LIKE ";
7173
public static final String IN =" IN ";
7274
public static final String LT = " < ";
7375
public static final String LTE = " <= ";
74-
public static final String GT = " > ";
76+
public static final String GT = " > ";
7577
public static final String GTE = " >= ";
7678
public static final String NE = " <> ";
7779
public static final String OR = " OR ";
7880
public static final String AND = " AND ";
79-
81+
8082
// ASC/DESC
8183
public static final String ORDER_BY = " ORDER BY ";
8284
public static final String ASCENDING = "ASC";
8385
public static final String DESCENDING = "DESC";
84-
86+
8587
public static final String DEFAULT_ORDERING = " ORDER BY RESOURCE_ID ASC ";
8688
public static final String DEFAULT_ORDERING_WITH_TABLE = " ORDER BY R.RESOURCE_ID ASC ";
87-
88-
// MIN / MAX
89+
90+
// MIN / MAX
8991
public static final String MAX = "MAX";
9092
public static final String MIN = "MIN";
9193

9294
/**
93-
* Maps search parameter types to the currently supported list of modifiers for
94-
* that type.
95+
* Calendar object to use while inserting Timestamp objects into the database.
96+
*/
97+
public static final Calendar UTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
98+
99+
/**
100+
* Maps search parameter types to the currently supported list of modifiers for that type.
95101
*/
96102
public static final Map<Type, List<Modifier>> supportedModifiersMap;
97103

@@ -123,4 +129,4 @@ public class JDBCConstants {
123129
private JDBCConstants() {
124130
// Hide the constructor
125131
}
126-
}
132+
}

0 commit comments

Comments
 (0)