You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2013/05/17 22:57:06 UTC
svn commit: r1483990 - in /sis/branches/JDK7:
core/sis-utility/src/main/java/org/apache/sis/internal/util/
core/sis-utility/src/test/java/org/apache/sis/internal/util/
core/sis-utility/src/test/java/org/apache/sis/test/suite/
ide-project/NetBeans/nbpro...
Author: desruisseaux
Date: Fri May 17 20:57:05 2013
New Revision: 1483990
URL: http://svn.apache.org/r1483990
Log:
Added support for date/time units in ChannelDecoder.
Added:
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java (with props)
Modified:
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties
sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/ChannelDecoderTest.java
Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java [UTF-8] Fri May 17 20:57:05 2013
@@ -16,8 +16,10 @@
*/
package org.apache.sis.internal.util;
+import java.util.Date;
import java.util.Formatter;
import java.util.FormattableFlags;
+import javax.xml.bind.DatatypeConverter;
import org.apache.sis.util.Static;
import org.apache.sis.util.CharSequences;
@@ -117,6 +119,103 @@ public final class Utilities extends Sta
}
/**
+ * Parses a date from a string in ISO 8601 format. More specifically, this method expects the
+ * format defined by <cite>XML Schema Part 2: Datatypes for {@code xsd:dateTime}</cite>, with
+ * some additional flexibility (e.g. missing minutes or seconds fields are automatically added).
+ *
+ * @param date The date to parse, or {@code null}.
+ * @param defaultToUTC {@code true} if the default timezone shall be UTL, or {@code false} for locale default.
+ * @return The parsed date, or {@code null} if the given string was {@code null}.
+ * @throws IllegalArgumentException if the given date can not be parsed.
+ *
+ * @see DatatypeConverter#parseDateTime(String)
+ */
+ public static Date parseDateTime(String date, final boolean defaultToUTC) throws IllegalArgumentException {
+ if (date != null) {
+ date = CharSequences.trimWhitespaces(date);
+ if (!date.isEmpty()) {
+ /*
+ * Check for missing time fields and time zone. For example if the given date is
+ * "2005-09-22T00:00", then this block will complete it as "2005-09-22T00:00:00".
+ * In addition, a 'Z' suffix will be appended if 'defaultToUTC' is true.
+ */
+ int timeFieldStart = date.lastIndexOf('T') + 1; // 0 if there is no time field.
+ int timeFieldEnd = date.length(); // To be updated if there is a time field.
+ int missingFields = 0; // Number of missing time fields.
+ boolean hasTimeZone = date.charAt(timeFieldEnd - 1) == 'Z';
+ if (timeFieldStart != 0) {
+ if (hasTimeZone) {
+ timeFieldEnd--;
+ } else {
+ final int s = Math.max(date.indexOf('+', timeFieldStart),
+ date.indexOf('-', timeFieldStart));
+ hasTimeZone = (s >= 0);
+ if (hasTimeZone) {
+ timeFieldEnd = s;
+ }
+ }
+ missingFields = 2;
+ for (int i=timeFieldStart; i<timeFieldEnd; i++) {
+ if (date.charAt(i) == ':') {
+ if (--missingFields == 0) break;
+ }
+ }
+ }
+ /*
+ * At this point, we have determined if there is some missing fields.
+ * The timezone will be considered missing only if 'defaultToUTC' is true.
+ */
+ CharSequence modified = date;
+ hasTimeZone |= !defaultToUTC;
+ if (missingFields != 0 || !hasTimeZone) {
+ final StringBuilder buffer = new StringBuilder(date);
+ while (--missingFields >= 0) {
+ buffer.append(":00");
+ }
+ if (!hasTimeZone) {
+ buffer.append('Z');
+ }
+ modified = buffer;
+ }
+ /*
+ * Now ensure that all numbers have at least two digits.
+ */
+ int indexOfLastDigit = 0;
+ for (int i=modified.length(); --i >= 0;) {
+ char c = modified.charAt(i);
+ final boolean isDigit = (c >= '0' && c <= '9'); // Do not use Character.isDigit(char).
+ if (indexOfLastDigit == 0) {
+ // We were not scaning a number. Check if we are now starting doing so.
+ if (isDigit) {
+ indexOfLastDigit = i;
+ }
+ } else {
+ // We were scaning a number. Check if we found the begining.
+ if (!isDigit) {
+ if (indexOfLastDigit - i == 1) {
+ // Reuse the buffer if it exists, or create a new one otherwise.
+ final StringBuilder buffer;
+ if (modified == date) {
+ modified = buffer = new StringBuilder(date);
+ } else {
+ buffer = (StringBuilder) modified;
+ }
+ buffer.insert(i+1, '0');
+ }
+ indexOfLastDigit = 0;
+ }
+ }
+ }
+ /*
+ * Now delegate to the utility method provided in the JAXB packages.
+ */
+ return DatatypeConverter.parseDateTime(modified.toString()).getTime();
+ }
+ }
+ return null;
+ }
+
+ /**
* Formats the given character sequence to the given formatter. This method takes in account
* the {@link FormattableFlags#UPPERCASE} and {@link FormattableFlags#LEFT_JUSTIFY} flags.
*
Added: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java?rev=1483990&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java (added)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java [UTF-8] Fri May 17 20:57:05 2013
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import java.util.Date;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.apache.sis.test.Assert.*;
+import static org.apache.sis.test.TestUtilities.date;
+
+
+/**
+ * Tests the {@link Utilities} class.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 0.3
+ * @module
+ */
+public final strictfp class UtilitiesTest extends TestCase {
+ /**
+ * Tests the {@link Utilities#parseDateTime(String)} method with an explicit time zone.
+ */
+ @Test
+ public void testParseDateTime() {
+ final Date expected = date("2009-01-01 05:00:00");
+ assertEquals(expected, Utilities.parseDateTime("2009-01-01T06:00:00+01:00", false));
+ assertEquals(expected, Utilities.parseDateTime("2009-01-01T06:00:00+01:00", true));
+ }
+
+ /**
+ * Tests the {@link Utilities#parseDateTime(String)} method for a date in UTC time zone,
+ * either explicit or implicit.
+ */
+ @Test
+ public void testParseDateTimeUTC() {
+ final Date expected = date("2005-09-22 00:00:00");
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22T00:00:00Z", false));
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22T00:00:00Z", true));
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22T00:00:00", true));
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22T00:00", true));
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22T00", true));
+ assertEquals(expected, Utilities.parseDateTime("2005-09-22", true));
+ assertEquals(expected, Utilities.parseDateTime("2005-9-22", true));
+ }
+}
Propchange: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/UtilitiesTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] Fri May 17 20:57:05 2013
@@ -50,6 +50,7 @@ import org.junit.BeforeClass;
org.apache.sis.math.MathFunctionsTest.class,
org.apache.sis.math.StatisticsTest.class,
org.apache.sis.math.StatisticsFormatTest.class,
+ org.apache.sis.internal.util.UtilitiesTest.class,
// Collections.
org.apache.sis.internal.util.ReferenceQueueConsumerTest.class,
Modified: sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties [ISO-8859-1] Fri May 17 20:57:05 2013
@@ -92,6 +92,7 @@ run.classpath=\
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}:\
+ ${maven.repository}/edu/ucar/udunits/${netcdf.version}/udunits-${netcdf.version}.jar:\
${maven.repository}/joda-time/joda-time/${joda-time.version}/joda-time-${joda-time.version}.jar:\
${maven.repository}/org/slf4j/slf4j-api/${slf4j.version}/slf4j-api-${slf4j.version}.jar:\
${maven.repository}/org/slf4j/slf4j-jdk14/${slf4j.version}/slf4j-jdk14-${slf4j.version}.jar
Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] Fri May 17 20:57:05 2013
@@ -26,6 +26,8 @@ import java.io.EOFException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.lang.reflect.Array;
+import javax.measure.converter.UnitConverter;
+import javax.measure.converter.ConversionException;
import org.opengis.parameter.InvalidParameterCardinalityException;
import org.apache.sis.internal.jdk8.Function;
import org.apache.sis.internal.netcdf.Decoder;
@@ -33,10 +35,12 @@ import org.apache.sis.internal.netcdf.Va
import org.apache.sis.internal.netcdf.GridGeometry;
import org.apache.sis.internal.netcdf.WarningProducer;
import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.util.Utilities;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.iso.DefaultNameSpace;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.measure.Units;
/**
@@ -70,6 +74,12 @@ public final class ChannelDecoder extend
*/
private static final Locale NAME_LOCALE = Locale.US;
+ /**
+ * {@code true} if the default timezone is UTC, or {@code false} if it shall be the
+ * {@linkplain java.util.TimeZone#getDefault() system default}.
+ */
+ private static final boolean DEFAULT_TIMEZONE_IS_UTC = true;
+
/*
* NOTE: the names of the static constants below this point match the names used in the Backus-Naur Form (BNF)
* definitions in the NetCDF Classic and 64-bit Offset Format (1.0) specification (link in class javdoc),
@@ -586,14 +596,47 @@ public final class ChannelDecoder extend
return null;
}
+ /**
+ * Returns the value of the attribute of the given name as a date, or {@code null} if none.
+ * If there is more than one numeric value, only the first one is returned.
+ */
@Override
- public Date dateValue(String name) throws IOException {
- throw new UnsupportedOperationException();
+ public Date dateValue(final String name) throws IOException {
+ final Attribute attribute = findAttribute(name);
+ if (attribute != null && attribute.value != null) {
+ if (attribute.value instanceof String) try {
+ return Utilities.parseDateTime((String) attribute.value, DEFAULT_TIMEZONE_IS_UTC);
+ } catch (IllegalArgumentException e) {
+ warning("dateValue", e);
+ }
+ }
+ return null;
}
+ /**
+ * Converts the given numerical values to date, using the information provided in the given unit symbol.
+ * The unit symbol is typically a string like "<cite>days since 1970-01-01T00:00:00Z</cite>".
+ *
+ * @param values The values to convert. May contains {@code null} elements.
+ * @return The converted values. May contains {@code null} elements.
+ */
@Override
- public Date[] numberToDate(String symbol, Number... values) throws IOException {
- throw new UnsupportedOperationException();
+ public Date[] numberToDate(final String symbol, final Number... values) throws IOException {
+ final Date[] dates = new Date[values.length];
+ final String[] parts = symbol.split("(?i)\\bsince\\b");
+ if (parts.length == 2) try {
+ final UnitConverter converter = Units.valueOf(parts[0]).getConverterToAny(Units.MILLISECOND);
+ final long epoch = Utilities.parseDateTime(parts[1], DEFAULT_TIMEZONE_IS_UTC).getTime();
+ for (int i=0; i<values.length; i++) {
+ final Number value = values[i];
+ if (value != null) {
+ dates[i] = new Date(epoch + Math.round(converter.convert(value.doubleValue())));
+ }
+ }
+ } catch (ConversionException | IllegalArgumentException e) {
+ warning("numberToDate", e);
+ }
+ return dates;
}
@Override
Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java [UTF-8] Fri May 17 20:57:05 2013
@@ -18,11 +18,13 @@ package org.apache.sis.internal.netcdf;
import java.util.Date;
import java.io.IOException;
+import static org.opengis.wrapper.netcdf.IOTestCase.NCEP;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.apache.sis.test.TestUtilities.date;
import static org.apache.sis.storage.netcdf.AttributeNames.*;
+import static org.apache.sis.test.TestUtilities.date;
/**
@@ -88,4 +90,23 @@ public strictfp class DecoderTest extend
assertAttributeEquals(date("2005-09-22 00:00:00"), DATE_CREATED);
assertAttributeEquals((Date) null, DATE_MODIFIED);
}
+
+ /**
+ * Tests {@link Decoder#numberToDate(String, Number[])}.
+ *
+ * @throws IOException If an error occurred while reading the NetCDF file.
+ */
+ @Test
+ public void testNumberToDate() throws IOException {
+ final Decoder decoder = selectDataset(NCEP);
+ assertArrayEquals(new Date[] {
+ date("2005-09-22 00:00:00")
+ }, decoder.numberToDate("hours since 1992-1-1", 120312));
+
+ assertArrayEquals(new Date[] {
+ date("1970-01-09 18:00:00"),
+ date("1969-12-29 06:00:00"),
+ date("1993-04-10 00:00:00")
+ }, decoder.numberToDate("days since 1970-01-01T00:00:00Z", 8.75, -2.75, 8500));
+ }
}
Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/ChannelDecoderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/ChannelDecoderTest.java?rev=1483990&r1=1483989&r2=1483990&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/ChannelDecoderTest.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/ChannelDecoderTest.java [UTF-8] Fri May 17 20:57:05 2013
@@ -62,9 +62,4 @@ public final strictfp class ChannelDecod
protected boolean isSupplementalFormatSupported(final String format) {
return false;
}
-
- @Override
- public void testDateValue() {
- // Disabled for now
- }
}