diff --git a/src/acconfig.h b/src/acconfig.h
index 3e460635859a40f03e212eed599b29ce149e3c82..8a6820083d74c030ba510e19d6ac7faf08603341 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -407,6 +407,9 @@
 /* define this if #include <time.h> provides an external int timezone */
 #undef HAVE_EXTERNAL_TIMEZONE
 
+/* define this if #include <time.h> provides an external int altzone */
+#undef HAVE_EXTERNAL_ALTZONE
+
 /* define this if your struct tm has a tm_gmtoff */
 #undef STRUCT_TM_HAS_GMTOFF
 
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 407148ccf8dd8fda072080a827ba2f2e0a11ff2f..36dee6100abc7d30d938428dd96d81931dafe0d2 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5855,12 +5855,29 @@ time_t mktime_zone(struct tm *date, int other_timezone, int tz)
       normalised_time += 24*60*60;
     else if (normalised_time > 12*60*60)
       normalised_time -= 24*60*60;
+
 #ifdef STRUCT_TM_HAS___TM_GMTOFF
     retval += date->__tm_gmtoff;
 #elif defined(STRUCT_TM_HAS_GMTOFF)
     retval += date->tm_gmtoff;
+#elif defined(HAVE_EXTERNAL_TIMEZONE) && defined(HAVE_EXTERNAL_ALTZONE)
+    if (date->tm_isdst) {
+      retval -= altzone;
+    } else {
+      retval -= timezone;
+    }
 #else
-    normalised_time = retval - mktime(gmtime(&retval));
+    {
+      /* NB: The tm from gmtime(3F) will always have tm_isdst == 0,
+       *     but mktime() is always in the local time zone, and will
+       *     adjust it and tm_hour if the local time zone is in dst.
+       *     This causes an error of typically one hour in dst when
+       *     used without preadjustment.
+       */
+      struct tm gmt_tm = *gmtime(&retval);
+      gmt_tm.tm_isdst = date->tm_isdst;
+      normalised_time += retval - mktime(&gmt_tm);
+    }
 #endif
     retval += normalised_time + tz;
   }
diff --git a/src/configure.in b/src/configure.in
index cbf3371317bcd115b274ff900256a2d4fe9b720a..fff642f389069e9eed2f00cad16f1733706cbd2d 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -5017,6 +5017,24 @@ fi
 
 AC_MSG_RESULT($pike_cv_has_external_timezone)
 
+AC_MSG_CHECKING(extern int altzone)
+
+AC_CACHE_VAL(pike_cv_has_external_altzone,[
+AC_TRY_LINK([
+#include <time.h>
+],[
+  int _tz;
+  _tz=altzone;
+  altzone=_tz;
+],pike_cv_has_external_altzone=yes,pike_cv_has_external_altzone=no)
+])
+
+if test "$pike_cv_has_external_altzone" = "yes"; then
+  AC_DEFINE(HAVE_EXTERNAL_ALTZONE)
+fi
+
+AC_MSG_RESULT($pike_cv_has_external_altzone)
+
 #############################################################################
 
 # No test for this yet...