diff --git a/src/xpdev/Makefile b/src/xpdev/Makefile
index 4c2d0586b4507e0eb9622f59e6a184ed4b9d271f..43f436b6b579f44b5e91fc32bdebd9ceeb5ed2a3 100644
--- a/src/xpdev/Makefile
+++ b/src/xpdev/Makefile
@@ -24,6 +24,10 @@ $(WRAPTEST): $(XPDEV-MT_LIB_BUILD) $(TESTOBJS) $(EXEODIR)
 	@echo Linking $<
 	$(QUIET)$(CC) $(LDFLAGS) $(MT_LDFLAGS) $(XPDEV-MT_CFLAGS) $(XPDEV-MT_LDFLAGS) -e$@ $(TESTOBJS) $(XPDEV-MT_LIBS)
 
+$(XPTIME): $(XPDEV_LIB_BUILD) $(OBJODIR)$(DIRSEP)xptime$(OFILE)
+	@echo Linking $<
+	$(QUIET)$(CC) $(LDFLAGS) $(LDFLAGS) $(XPDEV-CFLAGS) $(XPDEV-LDFLAGS) -e$@ $** $(XPDEV-LIBS)
+
 $(XPDEV_LIB_BUILD): $(OBJS)
 	@echo Creating $< ...
 	-$(QUIET)$(DELETE) $@
diff --git a/src/xpdev/objects.mk b/src/xpdev/objects.mk
index 7f46382958b6966fc553cf927153119c7af63a3e..3338504b52ca5e42ee2a7159783c70325b91e9e4 100644
--- a/src/xpdev/objects.mk
+++ b/src/xpdev/objects.mk
@@ -21,6 +21,7 @@ OBJS	= \
 	$(OBJODIR)$(DIRSEP)str_list$(OFILE) \
 	$(OBJODIR)$(DIRSEP)strwrap$(OFILE) \
 	$(OBJODIR)$(DIRSEP)xpbeep$(OFILE) \
+	$(OBJODIR)$(DIRSEP)xpdatetime$(OFILE) \
 	$(OBJODIR)$(DIRSEP)xpprintf$(OFILE)
 
 
@@ -42,6 +43,7 @@ MTOBJS	= \
 	$(MTOBJODIR)$(DIRSEP)strwrap$(OFILE) \
 	$(MTOBJODIR)$(DIRSEP)threadwrap$(OFILE) \
 	$(MTOBJODIR)$(DIRSEP)xpbeep$(OFILE) \
+	$(MTOBJODIR)$(DIRSEP)xpdatetime$(OFILE) \
 	$(MTOBJODIR)$(DIRSEP)xpprintf$(OFILE)
 
 TESTOBJS = \
diff --git a/src/xpdev/targets.mk b/src/xpdev/targets.mk
index 82e8f878cd1aa426223a49ca200368d41f4af1fd..1d0b7eea8dfbf3d31f9a7a4068e514a14e0e2141 100644
--- a/src/xpdev/targets.mk
+++ b/src/xpdev/targets.mk
@@ -7,6 +7,7 @@
 # ODIR, DIRSEP, LIBFILE, EXEFILE, and DELETE must be pre-defined
 
 WRAPTEST		= $(EXEODIR)$(DIRSEP)wraptest$(EXEFILE)
+XPTIME			= $(EXEODIR)$(DIRSEP)xptime$(EXEFILE)
 XPDEV_LIB_BUILD	= $(LIBODIR)$(DIRSEP)$(LIBPREFIX)xpdev$(LIBFILE)
 XPDEV-MT_LIB_BUILD	= $(LIBODIR)$(DIRSEP)$(LIBPREFIX)xpdev_mt$(LIBFILE)
 XPDEV_SHLIB_BUILD	= $(LIBODIR)$(DIRSEP)$(LIBPREFIX)xpdev$(SOFILE)
@@ -26,4 +27,6 @@ mtlib:	$(MTOBJODIR) $(LIBODIR) $(XPDEV-MT_LIB_BUILD)
 
 dl-mtlib: $(MTOBJODIR) $(LIBODIR) $(XPDEV-MT_SHLIB_BUILD)
 
+xptime: $(OBJODIR) $(LIBODIR) $(EXEODIR) $(XPTIME)
+
 $(WRAPTEST): $(XPDEV-MT_LIB_BUILD)
diff --git a/src/xpdev/unixtime.c b/src/xpdev/unixtime.c
deleted file mode 100644
index bca5780955efd27ad112af523b0982a1d96d23b0..0000000000000000000000000000000000000000
--- a/src/xpdev/unixtime.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* $Id$ */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#ifndef __unix__
-#include <dos.h>
-#endif
-#include <ctype.h>
-#define USE_SNPRINTF	/* we don't need safe_snprintf for this project */
-#include "genwrap.h"
-#include "datewrap.h"
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	char *p;
-	struct tm t;
-
-	memset(&t,0,sizeof(t));
-	t.tm_year=((str[6]&0xf)*10)+(str[7]&0xf);
-	if(t.tm_year<70)
-		t.tm_year+=100;
-	t.tm_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-	if(t.tm_mon) t.tm_mon--;
-	t.tm_mday=((str[3]&0xf)*10)+(str[4]&0xf);
-	p=strchr(str,' ');
-	if(p) {
-		t.tm_hour=atoi(++p);
-		p=strchr(p,':');
-		if(p) {
-			t.tm_min=atoi(++p);
-			p=strchr(p,':');
-			if(p)
-				t.tm_sec=atoi(++p); } }
-	return(mktime(&t));
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-	memset(&tm,0,sizeof(tm));
-	tm.tm_year=94;
-	tm.tm_mday=1;
-	return(mktime(&tm)^0x2D24BD00L);
-}
-
-int main(int argc, char **argv)
-{
-	char		str[256];
-	char		revision[16];
-	time_t		t;
-	struct tm*	tm;
-	int			argn=1;
-
-	printf("\n");
-	DESCRIBE_COMPILER(str);
-	sscanf("$Revision$", "%*s %s", revision);
-
-	printf("Rev %s Built " __DATE__ " " __TIME__ " with %s\n\n", revision, str);
-
-#if 0
-
-	if((t=checktime())!=0L) {
-		printf("Time problem (%08lX)\n",t);
-		exit(1); }
-#endif
-
-	if(argc<2)
-		printf("usage: unixtime [-z] <MM/DD/YY HH:MM:SS || time_t>\n\n");
-
-	if(argc>1 && stricmp(argv[1],"-z")==0)	{ /* zulu/GMT/UTC timezone */
-		printf("Setting timezone to Zulu/GMT/UTC\n\n");
-		putenv("TZ=UTC0");
-		argn++;
-	}
-	tzset();
-
-	printf("Current timezone: %d\n", xpTimeZone_local());
-	printf("\n");
-
-	if(argc>argn && argv[argn][2]=='/') {
-		sprintf(str,"%s %s",argv[argn],argc>argn+1 ? argv[argn+1] : "");
-		if((t=dstrtounix(str))==-1) {
-			printf("dstrtounix error\n");
-			return -1;
-		}
-		printf("Using specified date and time: ");
-	} else if(argc>argn) {
-		printf("Using specified time_t value: ");
-		t=strtoul(argv[argn],NULL,0);
-	} else {
-		printf("Using current time_t value: ");
-		t=time(NULL);
-	}
-	printf("%ld (%08lX)\n", t, t);
-	if((tm=localtime(&t))==NULL)
-		printf("localtime() failure\n");
-	else
-		printf("%-8s %.24s\n","local", asctime(tm));
-	if((tm=gmtime(&t))==NULL)
-		printf("gmtime() failure\n");
-	else
-		printf("%-8s %.24s\n","GMT", asctime(tm));
-
-	return(0);
-}
diff --git a/src/xpdev/xptime.c b/src/xpdev/xptime.c
new file mode 100644
index 0000000000000000000000000000000000000000..ec25f16ef36e158c14b6f377e0b7e9e82bad83d2
--- /dev/null
+++ b/src/xpdev/xptime.c
@@ -0,0 +1,112 @@
+/* $Id$ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#ifndef __unix__
+#include <dos.h>
+#endif
+#include <ctype.h>
+#define USE_SNPRINTF	/* we don't need safe_snprintf for this project */
+#include "genwrap.h"
+#include "datewrap.h"
+#include "xpdatetime.h"
+
+time_t checktime()
+{
+	struct tm tm;
+
+	memset(&tm,0,sizeof(tm));
+	tm.tm_year=94;
+	tm.tm_mday=1;
+	return(mktime(&tm)^0x2D24BD00L);
+}
+
+int main(int argc, char **argv)
+{
+	char			str[256];
+	char			revision[16];
+	time_t			t;
+	struct tm*		tp;
+	struct tm		tm;
+	int				argn=1;
+	xpDateTime_t	xpDateTime;
+
+	printf("\n");
+	DESCRIBE_COMPILER(str);
+	sscanf("$Revision$", "%*s %s", revision);
+
+	printf("Rev %s Built " __DATE__ " " __TIME__ " with %s\n\n", revision, str);
+
+#if 0
+
+	if((t=checktime())!=0L) {
+		printf("Time problem (%08lX)\n",t);
+		exit(1); }
+#endif
+
+	if(argc<2)
+		printf("usage: xptime [-z] <date_str || time_t>\n\n");
+
+	if(argc>1 && stricmp(argv[1],"-z")==0)	{ /* zulu/GMT/UTC timezone */
+		printf("Setting timezone to Zulu/GMT/UTC\n\n");
+		putenv("TZ=UTC0");
+		argn++;
+	}
+	tzset();
+
+	printf("Current timezone: %d\n", xpTimeZone_local());
+	printf("\n");
+
+	if(argc>argn && strlen(argv[argn]) > 10) {
+		xpDateTime=isoDateTimeStr_parse(argv[argn]);
+		t=xpDateTime_to_time(xpDateTime);
+		printf("Using specified date and time:\n");
+	} else if(argc>argn) {
+		printf("Using specified time_t value:\n");
+		t=strtoul(argv[argn],NULL,0);
+		xpDateTime=time_to_xpDateTime(t,xpTimeZone_LOCAL);
+	} else {
+		printf("Using current time:\n");
+		xpDateTime=xpDateTime_now();
+		t=time(NULL);
+	}
+	printf("%-8s %-10ld  (0x%08lX)    ISO %s\n"
+		,"time_t"
+		,t, t
+		,xpDateTime_to_isoDateTimeStr(xpDateTime
+			,NULL, " ", NULL
+			,/* precision: */3
+			, str, sizeof(str)));
+	{
+		const char* fmt="%-8s %.24s    ISO %s\n";
+
+		if((tp=localtime_r(&t, &tm))==NULL)
+			printf("localtime() failure\n");
+		else
+			printf(fmt
+				,"local"
+				,asctime(tp)
+				,xpDateTime_to_isoDateTimeStr(
+					time_to_xpDateTime(t, xpTimeZone_LOCAL)
+					,NULL, " ", NULL
+					,/*precision: */0
+					,str, sizeof(str))
+				);
+		if((tp=gmtime_r(&t, &tm))==NULL)
+			printf("gmtime() failure\n");
+		else
+			printf(fmt
+				,"GMT"
+				,asctime(tp)
+				,xpDateTime_to_isoDateTimeStr(
+					gmtime_to_xpDateTime(t)
+					,NULL, " ", NULL
+					,/*precision: */0
+					,str, sizeof(str))
+				);
+	}
+
+	return(0);
+}