Trigger    *trigger;        /* to get trigger name */
    int         nargs;          /* # of arguments */
    int         attnum;         /* positional number of field to change */
+   Oid         atttypid;       /* type OID of field to change */
    Datum       newdt;          /* The current datetime. */
    char      **args;           /* arguments */
    char       *relname;        /* triggered relation name */
    /* must be the field layout? */
    tupdesc = rel->rd_att;
 
-   /* Get the current datetime. */
-   newdt = DirectFunctionCall3(timestamp_in,
-                               CStringGetDatum("now"),
-                               ObjectIdGetDatum(InvalidOid),
-                               Int32GetDatum(-1));
-
    /*
     * This gets the position in the tuple of the field we want. args[0] being
     * the name of the field to update, as passed in from the trigger.
    attnum = SPI_fnumber(tupdesc, args[0]);
 
    /*
-    * This is were we check to see if the field we are supposed to update
-    * even exits.  The above function must return -1 if name not found?
+    * This is where we check to see if the field we are supposed to update
+    * even exists. The above function must return -1 if name not found?
     */
    if (attnum < 0)
        ereport(ERROR,
                        relname, args[0])));
 
    /*
-    * OK, this is where we make sure the timestamp field that we are
-    * modifying is really a timestamp field. Hay, error checking, what a
-    * novel idea !-)
+    * Check the target field has an allowed type, and get the current
+    * datetime as a value of that type.
     */
-   if (SPI_gettypeid(tupdesc, attnum) != TIMESTAMPOID)
+   atttypid = SPI_gettypeid(tupdesc, attnum);
+   if (atttypid == TIMESTAMPOID)
+       newdt = DirectFunctionCall3(timestamp_in,
+                                   CStringGetDatum("now"),
+                                   ObjectIdGetDatum(InvalidOid),
+                                   Int32GetDatum(-1));
+   else if (atttypid == TIMESTAMPTZOID)
+       newdt = DirectFunctionCall3(timestamptz_in,
+                                   CStringGetDatum("now"),
+                                   ObjectIdGetDatum(InvalidOid),
+                                   Int32GetDatum(-1));
+   else
+   {
        ereport(ERROR,
                (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
-                errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP",
+                errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP or TIMESTAMPTZ",
                        args[0], relname)));
+       newdt = (Datum) 0;      /* keep compiler quiet */
+   }
 
 /* 1 is the number of items in the arrays attnum and newdt.
    attnum is the positional number of the field to be updated.
    newdt is the new datetime stamp.
-   NOTE that attnum and newdt are not arrays, but then a 1 ellement array
+   NOTE that attnum and newdt are not arrays, but then a 1 element array
    is not an array any more then they are.  Thus, they can be considered a
    one element array.
 */