[m-rev.] for review: Java implementation of time library now tested and correct

James Goddard goddardjames at yahoo.com
Tue Dec 16 14:28:07 AEDT 2003


Estimated hours taken: 8
Branches: main

Implemented some library functions for the time library in java.

library/time.m:
	Foreign type "time_t_rep" implemented as instances of "java.util.Date".

	Implemented the following predicates in java:

		time__c_time/3
		time__time_t_is_invalid/1
		time__c_difftime/3
		time__c_localtime/10
		time__c_gmtime/10
		time__c_mktime/10

Index: time.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/time.m,v
retrieving revision 1.38
diff -u -d -r1.38 time.m
--- time.m	2 Nov 2003 01:04:24 -0000	1.38
+++ time.m	16 Dec 2003 02:57:39 -0000
@@ -216,6 +216,9 @@
 :- pragma foreign_type(il, time_t_rep, "valuetype [mscorlib]System.DateTime")
 	where comparison is compare_time_t_reps.
 
+:- pragma foreign_type("Java", time_t_rep, "java.util.Date")
+	where comparison is compare_time_t_reps.
+
 :- pred compare_time_t_reps(comparison_result::uo,
 		time_t_rep::in, time_t_rep::in) is det.
 compare_time_t_reps(Result, X, Y) :-
@@ -253,27 +256,24 @@
 }").
 */
 
+% XXX Java implementation still to come, will require some native code.
+
 %-----------------------------------------------------------------------------%
 
 %:- func time__clocks_per_sec = int.
 
-time__clocks_per_sec = Val :-
-	time__c_clocks_per_sec(Val).
-
-:- pred time__c_clocks_per_sec(int).
-:- mode time__c_clocks_per_sec(out) is det.
-
-:- pragma foreign_proc("C", time__c_clocks_per_sec(Ret::out),
+:- pragma foreign_proc("C", time__clocks_per_sec = (Ret::out),
 	[will_not_call_mercury, promise_pure],
 "{
 	Ret = (MR_Integer) CLOCKS_PER_SEC;
 }").
-:- pragma foreign_proc("C#", time__c_clocks_per_sec(Ret::out),
+:- pragma foreign_proc("C#", time__clocks_per_sec = (Ret::out),
 	[will_not_call_mercury, promise_pure],
 "{
 	// TicksPerSecond is guaranteed to be 10,000,000
 	Ret = (int) System.TimeSpan.TicksPerSecond;
 }").
+% XXX Java implementation still to come, will require some native code.
 
 %-----------------------------------------------------------------------------%
 
@@ -312,6 +312,8 @@
 	MR_update_io(IO0, IO);
 }").
 
+% XXX Java implementation still to come, will require some native code.
+
 %-----------------------------------------------------------------------------%
 
 time__clk_tck = Ret :-
@@ -339,12 +341,15 @@
 	Ret = -1;
 #endif
 }").
+time__c_clk_tck = -1.	% default is to throw an exception.
+
 :- pragma foreign_proc("C#", time__clk_tck = (Ret::out),
 	[will_not_call_mercury, promise_pure],
 "{
 	// TicksPerSecond is guaranteed to be 10,000,000
 	Ret = (int) System.TimeSpan.TicksPerSecond;
 }").
+% XXX Java implementation still to come, will require some native code.
 
 %-----------------------------------------------------------------------------%
 
@@ -375,6 +380,18 @@
 "{
 	Ret = System.DateTime.UtcNow;
 }").
+:- pragma foreign_proc("Java",
+	time__c_time(Ret::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	// Milliseconds should be discarded so that
+	//	mktime(localtime(Time)) == Time
+
+	java.util.GregorianCalendar gc = new java.util.GregorianCalendar();
+	gc.set(java.util.Calendar.MILLISECOND, 0);
+
+	Ret = gc.getTime();
+").
 
 :- pred time__time_t_is_invalid(time_t_rep).
 :- mode time__time_t_is_invalid(in) is semidet.
@@ -391,7 +408,12 @@
 "{
 	SUCCESS_INDICATOR = false;
 }").
-
+:- pragma foreign_proc("Java",
+	time__time_t_is_invalid(_Val::in),
+	[will_not_call_mercury, promise_pure],
+"
+	succeeded = false;
+").
 
 
 %-----------------------------------------------------------------------------%
@@ -418,6 +440,12 @@
 	span = T1 - T0;
 	Diff = span.TotalSeconds;
 }").
+:- pragma foreign_proc("Java",
+	time__c_difftime(T1::in, T0::in, Diff::out),
+	[will_not_call_mercury, promise_pure],
+"
+	Diff = (double) (T1.getTime() - T0.getTime()) / 1000;
+").
 
 %-----------------------------------------------------------------------------%
 
@@ -483,6 +511,55 @@
 		N = 0;
 	}
 }").
+:- pragma foreign_proc("Java",
+	time__c_localtime(Time::in, Yr::out, Mnt::out, MD::out, Hrs::out,
+		Min::out, Sec::out, YD::out, WD::out, N::out),
+	[will_not_call_mercury, promise_pure],
+"
+	java.util.GregorianCalendar gc = new java.util.GregorianCalendar();
+
+	gc.setTime(Time);
+	Yr = gc.get(java.util.Calendar.YEAR) - 1900;
+	Mnt = gc.get(java.util.Calendar.MONTH);
+	MD = gc.get(java.util.Calendar.DAY_OF_MONTH);
+	Hrs = gc.get(java.util.Calendar.HOUR_OF_DAY);
+	Min = gc.get(java.util.Calendar.MINUTE);
+	Sec = gc.get(java.util.Calendar.SECOND);
+	YD = gc.get(java.util.Calendar.DAY_OF_YEAR) - 1;
+
+	switch (gc.get(java.util.Calendar.DAY_OF_WEEK)) {
+		case java.util.Calendar.SUNDAY:
+			WD = 0;
+			break;
+		case java.util.Calendar.MONDAY:
+			WD = 1;
+			break;
+		case java.util.Calendar.TUESDAY:
+			WD = 2;
+			break;
+		case java.util.Calendar.WEDNESDAY:
+			WD = 3;
+			break;
+		case java.util.Calendar.THURSDAY:
+			WD = 4;
+			break;
+		case java.util.Calendar.FRIDAY:
+			WD = 5;
+			break;
+		case java.util.Calendar.SATURDAY:
+			WD = 6;
+			break;
+		default:
+			throw new RuntimeException(
+				""invalid DAY_OF_WEEK in time__c_local_time"");
+	}
+
+	if (gc.getTimeZone().inDaylightTime(Time)) {
+		N = 1;
+	} else {
+		N = 0;
+	}
+"). % time__c_local_time
 
 
 %:- func time__gmtime(time_t) = tm.
@@ -539,6 +616,53 @@
 	// UTC time can never have daylight savings.
 	N = 0;
 }").
+:- pragma foreign_proc("Java",
+	time__c_gmtime(Time::in, Yr::out, Mnt::out, MD::out, Hrs::out,
+		Min::out, Sec::out, YD::out, WD::out, N::out),
+	[will_not_call_mercury, promise_pure],
+"
+	java.util.GregorianCalendar gc =
+			new java.util.GregorianCalendar(
+			java.util.SimpleTimeZone.getTimeZone(""GMT""));
+
+	gc.setTime(Time);
+	Yr = gc.get(java.util.Calendar.YEAR) - 1900;
+	Mnt = gc.get(java.util.Calendar.MONTH);
+	MD = gc.get(java.util.Calendar.DAY_OF_MONTH);
+	Hrs = gc.get(java.util.Calendar.HOUR_OF_DAY);
+	Min = gc.get(java.util.Calendar.MINUTE);
+	Sec = gc.get(java.util.Calendar.SECOND);
+	YD = gc.get(java.util.Calendar.DAY_OF_YEAR) - 1;
+
+	switch (gc.get(java.util.Calendar.DAY_OF_WEEK)) {
+		case java.util.Calendar.SUNDAY:
+			WD = 0;
+			break;
+		case java.util.Calendar.MONDAY:
+			WD = 1;
+			break;
+		case java.util.Calendar.TUESDAY:
+			WD = 2;
+			break;
+		case java.util.Calendar.WEDNESDAY:
+			WD = 3;
+			break;
+		case java.util.Calendar.THURSDAY:
+			WD = 4;
+			break;
+		case java.util.Calendar.FRIDAY:
+			WD = 5;
+			break;
+		case java.util.Calendar.SATURDAY:
+			WD = 6;
+			break;
+		default:
+			throw new RuntimeException(
+				""invalid DAY_OF_WEEK in time__c_gmtime"");
+	}
+
+	N = 0;
+"). % time__c_gmtime
 
 :- func int_to_maybe_dst(int) = maybe(dst).
 
@@ -598,6 +722,39 @@
 		new System.DateTime(Yr + 1900, Mnt + 1, MD, Hrs, Min, Sec);
 	Time = local_time.ToUniversalTime();
 }").
+:- pragma foreign_proc("Java",
+	time__c_mktime(Yr::in, Mnt::in, MD::in, Hrs::in, Min::in, Sec::in,
+		_YD::in, _WD::in, N::in, Time::out),
+	[will_not_call_mercury, promise_pure],
+"
+	java.util.GregorianCalendar gc = new java.util.GregorianCalendar(
+			Yr + 1900, Mnt, MD, Hrs, Min, Sec);
+
+	Time = gc.getTime();
+
+	// Correct for DST:  This is only an issue for 2 hours of the year.
+	// (In Melbourne, 2:00am-2:59am occur twice when leaving DST)
+
+	// If the time we constructed is not in daylight savings time, but
+	// it should be, we need to subtract 1 hour.
+	if (N == 1 && gc.getTimeZone().inDaylightTime(Time) == false) {
+		Time.setTime(Time.getTime() - 3600000);
+		if (gc.getTimeZone().inDaylightTime(Time) == false) {
+			throw new RuntimeException(
+				""time__mktime: failed to correct for DST"");
+		}
+	}
+
+	// If the time we constructed is in daylight savings time, but
+	// should not be, we need to add 1 hour.
+	if (N == 0 && gc.getTimeZone().inDaylightTime(Time) == true) {
+		Time.setTime(Time.getTime() + 3600000);
+		if (gc.getTimeZone().inDaylightTime(Time) == true) {
+			throw new RuntimeException(
+				""time__mktime: failed to correct for DST"");
+		}
+	}
+").
 
 :- func maybe_dst_to_int(maybe(dst)) = int.
 
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list