diff --git a/lib/modules/Sql.pmod/odbc.pike b/lib/modules/Sql.pmod/odbc.pike
index 2fbc1d5ad93f77a13850e9f42e743863efb7ab63..2442fa3cb537d3608c84b2d1a3bccd9bc8e1b810 100644
--- a/lib/modules/Sql.pmod/odbc.pike
+++ b/lib/modules/Sql.pmod/odbc.pike
@@ -51,6 +51,44 @@ class typed_result
     return Gmp.mpq(mantissa, 10->pow(-scale));
   }
 
+  //! Time of day.
+  class TOD(int hour, int minute, int second,
+	    int|void nanos)
+  {
+    protected string _sprintf(int c)
+    {
+      if (nanos) {
+	return sprintf("%02d:%02d:%02d.%09d",
+		       hour, minute, second, nanos);
+      }
+      return sprintf("%02d:%02d:%02d", hour, minute, second);
+    }
+
+    protected mixed cast(string t)
+    {
+      switch(t) {
+      case "string":
+	return _sprintf('s');
+      case "int":
+	// Number of seconds since the start of the day.
+	return (hour*60 + minute)*60 + second;
+      case "float":
+	int seconds = cast("int");
+	return seconds + nanos/1000000000.0;
+      }
+      return UNDEFINED;
+    }
+  }
+
+  //! Function called to create time of day objects.
+  //!
+  //! The default implementation just passes along its
+  //! arguments to @[TOD].
+  TOD time_factory(int hour, int minute, int second, int|void nanos)
+  {
+    return TOD(hour, minute, second, nanos);
+  }
+
   //! Function called to create timestamp and date objects.
   //!
   //! @note
diff --git a/src/modules/Odbc/odbc_result.c b/src/modules/Odbc/odbc_result.c
index 95ee1188f4b6f5c13449911c64876b4bee98219f..8f1fdb18bd886f62e48dcf6cb7cabbee15be2d96 100644
--- a/src/modules/Odbc/odbc_result.c
+++ b/src/modules/Odbc/odbc_result.c
@@ -71,6 +71,7 @@ int odbc_result_fun_num = -1;
 int odbc_typed_result_fun_num = -1;
 
 static int scale_numeric_fun_num = -1;
+static int time_factory_fun_num = -1;
 static int timestamp_factory_fun_num = -1;
 
 /*
@@ -211,6 +212,25 @@ static void push_numeric(int i)
   free_string(data);
 }
 
+static void push_time(int i)
+{
+  struct pike_string *data = Pike_sp[-1].u.string;
+  struct tagTIME_STRUCT *time = (struct tagTIME_STRUCT *)(data->str);
+  if (data->len < sizeof(struct tagTIME_STRUCT)) {
+    return;
+  }
+  Pike_sp--;
+  push_int(time->hour);
+  push_int(time->minute);
+  push_int(time->second);
+#if 0
+  /* New in struct tagSS_TIME2_STRUCT. */
+  push_int(time->fraction);	/* ns */
+#endif
+  free_string(data);
+  apply_current(time_factory_fun_num, 3);
+}
+
 static void push_date(int i)
 {
   struct pike_string *data = Pike_sp[-1].u.string;
@@ -427,6 +447,12 @@ static void odbc_fix_fields(void)
       field_info[i].factory = push_date;
       break;
     case SQL_SS_TIME2:
+      /* This corresponds to MSSQL time, and is time of day
+       * with nanosecond precision.
+       *
+       * FIXME: We just convert it to SQL_C_TYPE_TIME for now.
+       */
+      /* FALL_THROUGH */
     case SQL_TIME:
       push_text("time");
       field_info[i].type = SQL_C_WCHAR;
@@ -434,6 +460,9 @@ static void odbc_fix_fields(void)
        *       wants bytes.
        */
       field_info[i].size = 32 * (ptrdiff_t)sizeof(SQLWCHAR);
+      field_info[i].bin_type = SQL_C_TYPE_TIME;
+      field_info[i].bin_size = sizeof(struct tagTIME_STRUCT);
+      field_info[i].factory = push_time;
       break;
     case SQL_SS_TIMESTAMPOFFSET:
       /* This corresponds to MSSQL datetimeoffset, and is
@@ -1336,6 +1365,10 @@ void init_odbc_res_programs(void)
     ADD_FUNCTION("scale_numeric", NULL,
 		 tFunc(tInt tInt, tOr(tInt, tObj)),
 		 ID_PUBLIC);
+  time_factory_fun_num =
+    ADD_FUNCTION("time_factory", NULL,
+		 tFunc(tInt tInt tInt tOr(tInt, tVoid), tMix),
+		 ID_PUBLIC);
   timestamp_factory_fun_num =
     ADD_FUNCTION("timestamp_factory", NULL,
 		 tFunc(tInt tInt tInt