| @@ -40,6 +40,7 @@ import org.apache.tools.ant.types.resources.FileProvider; | |||
| import org.apache.tools.ant.types.resources.FileResource; | |||
| import org.apache.tools.ant.types.resources.Touchable; | |||
| import org.apache.tools.ant.types.resources.Union; | |||
| import org.apache.tools.ant.util.DateUtils; | |||
| import org.apache.tools.ant.util.FileNameMapper; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| @@ -60,33 +61,20 @@ public class Touch extends Task { | |||
| DateFormat getFallbackFormat(); | |||
| } | |||
| /** | |||
| * Provides access to DateUtils.EN_US_DATE_FORMAT_MIN (primary) and | |||
| * DateUtils.EN_US_DATE_FORMAT_SEC (fallback). | |||
| */ | |||
| public static final DateFormatFactory DEFAULT_DF_FACTORY | |||
| = new DateFormatFactory() { | |||
| private ThreadLocal<DateFormat> primary = | |||
| new ThreadLocal<DateFormat>() { | |||
| @Override | |||
| protected DateFormat initialValue() { | |||
| return new SimpleDateFormat("MM/dd/yyyy hh:mm a", | |||
| Locale.US); | |||
| } | |||
| }; | |||
| private ThreadLocal<DateFormat> fallback = | |||
| new ThreadLocal<DateFormat>() { | |||
| @Override | |||
| protected DateFormat initialValue() { | |||
| return new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", | |||
| Locale.US); | |||
| } | |||
| }; | |||
| @Override | |||
| public DateFormat getPrimaryFormat() { | |||
| return primary.get(); | |||
| return DateUtils.EN_US_DATE_FORMAT_MIN.get(); | |||
| } | |||
| @Override | |||
| public DateFormat getFallbackFormat() { | |||
| return fallback.get(); | |||
| return DateUtils.EN_US_DATE_FORMAT_SEC.get(); | |||
| } | |||
| }; | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| @@ -29,8 +29,6 @@ import java.util.TimeZone; | |||
| import java.util.regex.Matcher; | |||
| import java.util.regex.Pattern; | |||
| import org.apache.tools.ant.taskdefs.Touch; | |||
| /** | |||
| * Helper methods to deal with date/time formatting with a specific | |||
| * defined format (<a href="http://www.w3.org/TR/NOTE-datetime">ISO8601</a>) | |||
| @@ -93,6 +91,32 @@ public final class DateUtils { | |||
| private static final ChoiceFormat SECONDS_FORMAT = | |||
| new ChoiceFormat(LIMITS, SECONDS_PART); | |||
| /** | |||
| * Provides a thread-local US-style date format. Exactly as used by | |||
| * {@code <touch>}, to minute precision: | |||
| * {@code SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US)} | |||
| */ | |||
| public static final ThreadLocal<DateFormat> EN_US_DATE_FORMAT_MIN = | |||
| new ThreadLocal<DateFormat>() { | |||
| @Override | |||
| protected DateFormat initialValue() { | |||
| return new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US); | |||
| } | |||
| }; | |||
| /** | |||
| * Provides a thread-local US-style date format. Exactly as used by | |||
| * {@code <touch>}, to second precision: | |||
| * {@code SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US)} | |||
| */ | |||
| public static final ThreadLocal<DateFormat> EN_US_DATE_FORMAT_SEC = | |||
| new ThreadLocal<DateFormat>() { | |||
| @Override | |||
| protected DateFormat initialValue() { | |||
| return new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US); | |||
| } | |||
| }; | |||
| static { | |||
| MINUTE_SECONDS.setFormat(0, MINUTES_FORMAT); | |||
| MINUTE_SECONDS.setFormat(1, SECONDS_FORMAT); | |||
| @@ -332,11 +356,11 @@ public final class DateUtils { | |||
| } catch (NumberFormatException nfe) {} | |||
| try { | |||
| return Touch.DEFAULT_DF_FACTORY.getPrimaryFormat().parse(dateStr); | |||
| return EN_US_DATE_FORMAT_MIN.get().parse(dateStr); | |||
| } catch (ParseException pe) {} | |||
| try { | |||
| return Touch.DEFAULT_DF_FACTORY.getFallbackFormat().parse(dateStr); | |||
| return EN_US_DATE_FORMAT_SEC.get().parse(dateStr); | |||
| } catch (ParseException pe) {} | |||
| Matcher m = iso8601normalizer.matcher(dateStr); | |||
| @@ -182,4 +182,24 @@ | |||
| <fileset dir="${basedir}" includes="zip-test.xml"/> | |||
| </zip> | |||
| </target> | |||
| <target name="testSetZipModTime"> | |||
| <mkdir dir="${input}/"/> | |||
| <touch file="${input}/test1.txt"/> | |||
| <mkdir dir="${output}"/> | |||
| <zip destfile="${output}/test.zip" basedir="${input}" modificationtime="2016-01-01 00:00"> | |||
| <fileset dir="${input}"/> | |||
| </zip> | |||
| <checksum file="${output}/test.zip" property="testSetZipModTime_hash" /> | |||
| <delete file="${output}/test.zip" /> | |||
| <touch file="${input}/test1.txt"/> | |||
| <zip destfile="${output}/test.zip" basedir="${input}" modificationtime="2016-01-01 00:00"> | |||
| <fileset dir="${input}"/> | |||
| </zip> | |||
| <checksum file="${output}/test.zip" property="testSetZipModTime_hash" verifyproperty="testSetZipModTime_okay" /> | |||
| <au:assertTrue> | |||
| <equals arg1="${testSetZipModTime_okay}" arg2="true" /> | |||
| </au:assertTrue> | |||
| </target> | |||
| </project> | |||