diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk
index ceb44f55194..a0f3dc7ff0a 100644
--- a/make/InitSupport.gmk
+++ b/make/InitSupport.gmk
@@ -23,6 +23,10 @@
# questions.
#
+# ===========================================================================
+# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+# ===========================================================================
+
################################################################################
# This file contains helper functions for Init.gmk.
# It is divided in two parts, depending on if a SPEC is present or not
@@ -311,7 +315,7 @@ else # $(HAS_SPEC)=true
define SetupReproducibleBuild
ifeq ($$(SOURCE_DATE), updated)
# For static values of SOURCE_DATE (not "updated"), these are set in spec.gmk
- export SOURCE_DATE_EPOCH := $$(shell $$(DATE) +"%s")
+ export SOURCE_DATE_EPOCH := $$(shell $$(JAVA) $$(TOPDIR)/make/src/classes/DateUtil.java)
export SOURCE_DATE_ISO_8601 := $$(call EpochToISO8601, $$(SOURCE_DATE_EPOCH))
endif
endef
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index 0413a50270c..1a74de605b9 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -23,6 +23,10 @@
# questions.
#
+# ===========================================================================
+# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+# ===========================================================================
+
###############################################################################
# Set the debug level
# release: no debug information, all optimizations, no asserts.
@@ -203,13 +207,9 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
elif test "x$with_copyright_year" != x; then
COPYRIGHT_YEAR="$with_copyright_year"
elif test "x$SOURCE_DATE" != xupdated; then
- if test "x$IS_GNU_DATE" = xyes; then
- COPYRIGHT_YEAR=`$DATE --date=@$SOURCE_DATE +%Y`
- else
- COPYRIGHT_YEAR=`$DATE -j -f %s $SOURCE_DATE +%Y`
- fi
+ COPYRIGHT_YEAR=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --format=yyyy --date="$SOURCE_DATE_EPOCH"`
else
- COPYRIGHT_YEAR=`$DATE +'%Y'`
+ COPYRIGHT_YEAR=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --format=yyyy`
fi
AC_SUBST(COPYRIGHT_YEAR)
@@ -674,7 +674,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD],
AC_MSG_RESULT([determined at build time, from 'updated'])
elif test "x$with_source_date" = xcurrent; then
# Set the current time
- SOURCE_DATE=$($DATE +"%s")
+ SOURCE_DATE=$($JAVA $TOPDIR/make/src/classes/DateUtil.java)
AC_MSG_RESULT([$SOURCE_DATE, from 'current'])
elif test "x$with_source_date" = xversion; then
# Use the date from version-numbers.conf
@@ -706,11 +706,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD],
# If we have a fixed value for SOURCE_DATE, we need to set SOURCE_DATE_EPOCH
# for the rest of configure.
SOURCE_DATE_EPOCH="$SOURCE_DATE"
- if test "x$IS_GNU_DATE" = xyes; then
- SOURCE_DATE_ISO_8601=`$DATE --utc --date="@$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null`
- else
- SOURCE_DATE_ISO_8601=`$DATE -u -j -f "%s" "$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null`
- fi
+ SOURCE_DATE_ISO_8601=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --date="$SOURCE_DATE" --format="yyyy-MM-dd'T'HH:mm:ss'Z'"`
fi
REPRODUCIBLE_BUILD_DEFAULT=$with_source_date_present
diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4
index d2171338d00..2db26b253dc 100644
--- a/make/autoconf/util.m4
+++ b/make/autoconf/util.m4
@@ -23,6 +23,10 @@
# questions.
#
+# ===========================================================================
+# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+# ===========================================================================
+
m4_include([util_paths.m4])
###############################################################################
@@ -234,24 +238,7 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES],
# $2: input date/time string
AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP],
[
- if test "x$IS_GNU_DATE" = xyes; then
- # GNU date
- timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null)
- else
- # BSD date
- # ISO-8601 date&time in Zulu 'date'T'time'Z
- timestamp=$($DATE -u -j -f "%FT%TZ" "$2" "+%s" 2> /dev/null)
- if test "x$timestamp" = x; then
- # BSD date cannot handle trailing milliseconds.
- # Try again ignoring characters at end
- timestamp=$($DATE -u -j -f "%Y-%m-%dT%H:%M:%S" "$2" "+%s" 2> /dev/null)
- fi
- if test "x$timestamp" = x; then
- # Perhaps the time was missing.
- timestamp=$($DATE -u -j -f "%FT%TZ" "$2""T00:00:00Z" "+%s" 2> /dev/null)
- fi
- fi
- $1=$timestamp
+ $1=$($JAVA $TOPDIR/make/src/classes/DateUtil.java --date="$2")
])
###############################################################################
diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk
index 6ec818b4f55..111051da9d3 100644
--- a/make/common/Utils.gmk
+++ b/make/common/Utils.gmk
@@ -23,6 +23,10 @@
# questions.
#
+# ===========================================================================
+# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+# ===========================================================================
+
ifeq (,$(_MAKEBASE_GMK))
$(error You must include MakeBase.gmk prior to including Utils.gmk)
endif
@@ -221,15 +225,7 @@ Or = \
# Convert an UNIX epoch based timestamp (as an integer) to an ISO 8601 date
# string.
# Param 1 - timestamp
-ifeq ($(IS_GNU_DATE), yes)
- EpochToISO8601 = \
- $(shell $(DATE) --utc --date="@$(strip $1)" \
- +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null)
-else
- EpochToISO8601 = \
- $(shell $(DATE) -u -j -f "%s" "$(strip $1)" \
- +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null)
-endif
+EpochToISO8601 = $(shell $(JAVA) $(TOPDIR)/make/src/classes/DateUtil.java --date="$(strip $1)" --format="yyyy-MM-dd'T'HH:mm:ss'Z'")
################################################################################
# Parse a multiple-keyword variable, like FOO="KEYWORD1=val1;KEYWORD2=val2;..."
diff --git a/make/src/classes/DateUtil.java b/make/src/classes/DateUtil.java
new file mode 100644
index 00000000000..914689ad810
--- /dev/null
+++ b/make/src/classes/DateUtil.java
@@ -0,0 +1,94 @@
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+ * ===========================================================================
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * IBM designates this particular file as subject to the "Classpath" exception
+ * as provided by IBM in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, see .
+ * ===========================================================================
+ */
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Locale;
+
+public class DateUtil {
+
+ public static void main(String... args) {
+ String date = "";
+ String format = "";
+
+ for (String arg : args) {
+ if (arg.startsWith("--date=")) {
+ date = arg.substring(7).trim();
+ } else if (arg.startsWith("--format=")) {
+ format = arg.substring(9).trim();
+ } else {
+ showUsageAndExit();
+ }
+ }
+
+ LocalDateTime time = parseTime(date);
+
+ if (format.isEmpty()) {
+ System.out.println(time.toEpochSecond(ZoneOffset.UTC));
+ } else {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format, Locale.ROOT);
+
+ System.out.println(formatter.format(time));
+ }
+ }
+
+ private static LocalDateTime parseTime(String text) {
+ if (text.isEmpty()) {
+ return LocalDateTime.now(ZoneOffset.UTC);
+ }
+
+ if (text.matches("\\d+")) {
+ return LocalDateTime.ofEpochSecond(Long.parseLong(text), 0, ZoneOffset.UTC);
+ }
+
+ try {
+ return LocalDateTime.ofInstant(Instant.parse(text), ZoneOffset.UTC);
+ } catch (DateTimeParseException e) {
+ // try next format
+ }
+
+ try {
+ return LocalDateTime.parse(text);
+ } catch (DateTimeParseException e) {
+ // try next format
+ }
+
+ try {
+ return LocalDate.parse(text).atStartOfDay();
+ } catch (DateTimeParseException e) {
+ System.err.format("Cannot parse time: '%s'%n", text);
+ System.exit(1);
+ return null;
+ }
+ }
+
+ private static void showUsageAndExit() {
+ System.err.println("Usage: DateUtil [options]");
+ System.err.println(" --date=