13
13
import java .net .URISyntaxException ;
14
14
import java .net .URL ;
15
15
import java .time .OffsetDateTime ;
16
+ import java .time .ZoneOffset ;
16
17
import java .time .format .DateTimeFormatter ;
17
18
import java .time .format .DateTimeParseException ;
18
19
import java .util .ArrayList ;
@@ -732,6 +733,10 @@ else if (TEMPORAL_AXIS_LABELS.contains(label)) {
732
733
extent .add (BigDecimal .valueOf (Double .parseDouble (minT )));
733
734
extent .add (BigDecimal .valueOf (Double .parseDouble (maxT )));
734
735
}
736
+ // units of the time dimension
737
+ if (label .toUpperCase ().equals (TimeUnit .YEAR .name ())) {
738
+ dim .setUnit (TimeUnit .YEAR .getAbbrv ());
739
+ }
735
740
dim .setExtent (extent );
736
741
cubeDimensions .put (label , dim );
737
742
}
@@ -896,15 +901,15 @@ else if (TEMPORAL_AXIS_LABELS.contains(label)) {
896
901
// TODO what to put when there is no time axis in the original coverage?
897
902
CollectionTemporalExtent temporalExtent = new CollectionTemporalExtent ();
898
903
List <List <OffsetDateTime >> intervals = new ArrayList <>();
899
-
904
+ List <OffsetDateTime > interval = new ArrayList <>();
905
+ DateTimeFormatter fmt = OffsetDateTimeSerializer .FORMATTER ;
906
+
900
907
if (hasTimeCrs ) {
901
908
// 1+ time dimensions:
902
909
for (DimensionTemporal dim : timeDims ) {
903
910
String minT = dim .getExtent ().get (0 );
904
911
String maxT = dim .getExtent ().get (1 );
905
-
906
- List <OffsetDateTime > interval = new ArrayList <>();
907
- DateTimeFormatter fmt = OffsetDateTimeSerializer .FORMATTER ;
912
+
908
913
try {
909
914
//STAC requires format: https://www.rfc-editor.org/rfc/rfc3339#section-5.6
910
915
interval .add (OffsetDateTime .parse (minT , fmt ));
@@ -917,9 +922,29 @@ else if (TEMPORAL_AXIS_LABELS.contains(label)) {
917
922
}
918
923
919
924
log .debug ("Time interval : " + interval );
920
-
921
925
intervals .add (interval );
922
926
}
927
+ } else {
928
+ // fetch other dimension with temporal type:
929
+ List <DimensionOther > otherTimeDims = cubeDimensions .values ().stream ()
930
+ .filter (dim -> dim instanceof DimensionOther )
931
+ .filter (dim -> TimeUnit .getAllAbbrv ().contains (((DimensionOther )dim ).getUnit ()))
932
+ .map (dim -> (DimensionOther ) dim )
933
+ .collect (Collectors .toList ());
934
+
935
+ switch (otherTimeDims .size ()) {
936
+ case 0 :
937
+ log .warn ("No time dimension found in coverage {}." , coverageID );
938
+ break ;
939
+ case 1 :
940
+ DimensionOther tDim = otherTimeDims .get (0 );
941
+ interval .addAll (toTimeExtent (tDim ));
942
+ intervals .add (interval );
943
+ break ;
944
+ default :
945
+ log .warn ("Multiple \" other\" time dimension found." );
946
+ break ;
947
+ }
923
948
}
924
949
temporalExtent .setInterval (intervals );
925
950
collectionExtent .setTemporal (temporalExtent );
@@ -1036,18 +1061,26 @@ else if (TEMPORAL_AXIS_LABELS.contains(label)) {
1036
1061
String tempStep = metadataElement .getChildText ("Temporal_Step" , gmlNS );
1037
1062
if (null != tempStep ) {
1038
1063
if (!hasTimeCrs ) {
1039
- log .warn ("Temporal step provided but time axis not found in coverage {}." , coverageID );
1040
-
1041
1064
// fetch other dimension with temporal type:
1042
1065
List <DimensionOther > otherTimeDims = cubeDimensions .values ().stream ()
1043
1066
.filter (dim -> TypeEnum .TEMPORAL .equals (dim .getType ()))
1044
1067
.filter (dim -> dim instanceof DimensionOther )
1045
1068
.map (dim -> (DimensionOther ) dim )
1046
1069
.collect (Collectors .toList ()); //Java 9: .toList());
1070
+ otherTimeDims .addAll (cubeDimensions .values ().stream ()
1071
+ .filter (dim -> dim instanceof DimensionOther )
1072
+ .filter (dim -> TimeUnit .getAllAbbrv ().contains (((DimensionOther )dim ).getUnit ()))
1073
+ .map (dim -> (DimensionOther ) dim )
1074
+ .collect (Collectors .toList ()));
1047
1075
1048
1076
for (DimensionOther dim : otherTimeDims ) {
1049
1077
dim .setStep (tempStep );
1050
1078
}
1079
+
1080
+ if (otherTimeDims .isEmpty ()) {
1081
+ log .warn ("Temporal step provided but time dimension not found in coverage {}." , coverageID );
1082
+ // (..or heuristic for converting other to time is incomplete)
1083
+ }
1051
1084
} else {
1052
1085
DimensionTemporal dim = timeDims .get (0 );
1053
1086
dim .setStep (tempStep );
@@ -1364,4 +1397,33 @@ else if (TEMPORAL_AXIS_LABELS.contains(label)) {
1364
1397
1365
1398
return currentCollection ;
1366
1399
}
1400
+
1401
+ /**
1402
+ * Converts the numeric extent of a dimension of type "other" but
1403
+ * with temporal meaning, to time extent (heuristic).
1404
+ *
1405
+ * @return from/to timestamp of the given time dimension.
1406
+ */
1407
+ private static final List <OffsetDateTime > toTimeExtent (DimensionOther dim ) {
1408
+ if (TypeEnum .TEMPORAL != dim .getType ()) {
1409
+ log .warn ("Input dimension is not temporal" );
1410
+ //return null;
1411
+ // lenient because if type is TEMPORAL the dimension is serialized as TemporalDim anyway in STAC!
1412
+ }
1413
+
1414
+ List <OffsetDateTime > timeExtent = null ;
1415
+
1416
+ if (dim .getUnit ().equals (TimeUnit .YEAR .getAbbrv ())) {
1417
+ int yFrom = dim .getExtent ().get (0 ).toBigInteger ().intValue ();
1418
+ int yUntl = dim .getExtent ().get (1 ).toBigInteger ().intValue ();
1419
+ OffsetDateTime from = OffsetDateTime .of (yFrom , 1 , 1 , 0 , 0 , 0 , 0 , ZoneOffset .UTC );
1420
+ OffsetDateTime untl = OffsetDateTime .of (yUntl , 12 , 31 , 23 , 59 , 59 , 0 , ZoneOffset .UTC );
1421
+ timeExtent = Arrays .asList (from , untl );
1422
+ } else {
1423
+ log .error ("No time decoding implemented for unit: {}" , dim .getUnit ());
1424
+ }
1425
+
1426
+ return timeExtent ;
1427
+ }
1428
+
1367
1429
}
0 commit comments