*** ./doc/src/sgml/func.sgml.orig	2005-06-06 20:17:14.000000000 -0300
--- ./doc/src/sgml/func.sgml	2005-06-06 20:26:59.000000000 -0300
***************
*** 8082,8087 ****
--- 8082,8093 ----
        </row>
  
        <row>
+        <entry><function>pg_start_time()</function></entry>
+        <entry><type>timestamp with time zone</type></entry>
+        <entry>PostgreSQL startup date and time</entry>
+       </row>
+ 
+       <row>
         <entry><function>user</function></entry>
         <entry><type>name</type></entry>
         <entry>equivalent to <function>current_user</function></entry>
***************
*** 8179,8184 ****
--- 8185,8199 ----
     </para>
  
     <indexterm zone="functions-info">
+     <primary>pg_start_time</primary>
+    </indexterm>
+ 
+    <para>
+      <function>pg_start_time()</function> returns the timestamp with time zone
+      which the <productname>PostgreSQL</productname> was started.
+    </para>
+ 
+    <indexterm zone="functions-info">
      <primary>version</primary>
     </indexterm>
  
*** ./src/backend/postmaster/postmaster.c.orig	2005-06-06 20:17:43.000000000 -0300
--- ./src/backend/postmaster/postmaster.c	2005-06-06 20:21:33.000000000 -0300
***************
*** 222,227 ****
--- 222,230 ----
  bool		ClientAuthInProgress = false;		/* T during new-client
  												 * authentication */
  
+ /* Backend startup time */
+ TimestampTz	StartTime;
+ 
  /*
   * State for assigning random salts and cancel keys.
   * Also, the global MyCancelKey passes the cancel key assigned to a given
***************
*** 330,335 ****
--- 333,339 ----
  	InheritableSocket pgStatPipe0;
  	InheritableSocket pgStatPipe1;
  	pid_t PostmasterPid;
+ 	TimestampTz StartTime;
  #ifdef WIN32
  	HANDLE PostmasterHandle;
  	HANDLE initial_signal_pipe;
***************
*** 372,377 ****
--- 376,384 ----
  	char	   *userDoption = NULL;
  	int			i;
  
+ 	AbsoluteTime		StartTimeSec;	/* integer part */
+ 	int			StartTimeUSec;	/* microsecond part */
+ 
  	/* This will call exit() if strdup() fails. */
  	progname = get_progname(argv[0]);	
  
***************
*** 914,919 ****
--- 921,932 ----
  	 */
  	StartupPID = StartupDataBase();
  
+ 	/*
+ 	 * Get start up time
+ 	 */
+ 	StartTimeSec = GetCurrentAbsoluteTimeUsec(&StartTimeUSec);
+ 	StartTime = AbsoluteTimeUsecToTimestampTz(StartTimeSec, StartTimeUSec);
+ 
  	status = ServerLoop();
  
  	/*
***************
*** 3603,3608 ****
--- 3616,3622 ----
  	write_inheritable_socket(&param->pgStatPipe1, pgStatPipe[1], childPid);
  
  	param->PostmasterPid = PostmasterPid;
+ 	param->StartTime = StartTime;
  
  #ifdef WIN32
  	param->PostmasterHandle = PostmasterHandle;
***************
*** 3805,3810 ****
--- 3819,3825 ----
  	read_inheritable_socket(&pgStatPipe[1], &param->pgStatPipe1);
  
  	PostmasterPid = param->PostmasterPid;
+ 	StartTime = param->StartTime;
  
  #ifdef WIN32
  	PostmasterHandle = param->PostmasterHandle;
*** ./src/backend/tcop/postgres.c.orig	2005-06-06 20:17:35.000000000 -0300
--- ./src/backend/tcop/postgres.c	2005-06-07 00:31:49.000000000 -0300
***************
*** 149,154 ****
--- 149,157 ----
  #endif   /* TCOP_DONTUSENEWLINE */
  
  
+ /* Backend startup time */
+ TimestampTz	StartTime;
+ 
  /* ----------------------------------------------------------------
   *		decls for routines only used in this file
   * ----------------------------------------------------------------
***************
*** 2380,2385 ****
--- 2383,2391 ----
  	sigjmp_buf	local_sigjmp_buf;
  	volatile bool send_rfq = true;
  
+ 	AbsoluteTime            StartTimeSec;   /* integer part */
+       int                     StartTimeUSec;  /* microsecond part */
+ 
  #define PendingConfigOption(name,val) \
  	(guc_names = lappend(guc_names, pstrdup(name)), \
  	 guc_values = lappend(guc_values, pstrdup(val)))
***************
*** 2970,2975 ****
--- 2976,2990 ----
  	pgstat_bestart();
  
  	/*
+ 	 * Get stand-alone backend startup time
+ 	 */
+ 	if (!IsUnderPostmaster)
+ 	{
+ 		StartTimeSec = GetCurrentAbsoluteTimeUsec(&StartTimeUSec);
+ 		StartTime = AbsoluteTimeUsecToTimestampTz(StartTimeSec, StartTimeUSec);
+ 	}
+ 
+ 	/*
  	 * POSTGRES main processing loop begins here
  	 *
  	 * If an exception is encountered, processing resumes here so we abort
*** ./src/backend/utils/adt/timestamp.c.orig	2005-06-06 20:17:42.000000000 -0300
--- ./src/backend/utils/adt/timestamp.c	2005-06-06 20:25:08.000000000 -0300
***************
*** 938,943 ****
--- 938,949 ----
  	PG_RETURN_TIMESTAMPTZ(result);
  }
  
+ Datum
+ pgsql_start_time(PG_FUNCTION_ARGS)
+ {
+ 	PG_RETURN_TIMESTAMPTZ(StartTime);
+ }
+ 
  void
  dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
  {
*** ./src/include/catalog/pg_proc.h.orig	2005-06-06 20:17:53.000000000 -0300
--- ./src/include/catalog/pg_proc.h	2005-06-07 00:43:08.000000000 -0300
***************
*** 3645,3650 ****
--- 3645,3654 ----
  DATA(insert OID = 2558 ( int4				   PGNSP PGUID 12 f f t f i 1  23 "16" _null_ _null_ _null_	bool_int4 - _null_ ));
  DESCR("convert boolean to int4");
  
+ /* start time function */
+ DATA(insert OID = 2559 (  pg_start_time PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_ pgsql_start_time - _null_ ));
+ DESCR("PostgreSQL start time");
+ 
  
  /*
   * Symbolic values for provolatile column: these indicate whether the result
*** ./src/include/utils/timestamp.h.orig	2005-06-06 20:17:44.000000000 -0300
--- ./src/include/utils/timestamp.h	2005-06-06 20:23:29.000000000 -0300
***************
*** 256,261 ****
--- 256,265 ----
  
  extern Datum now(PG_FUNCTION_ARGS);
  
+ extern Datum pgsql_start_time(PG_FUNCTION_ARGS);
+ 
+ extern TimestampTz StartTime;
+ 
  /* Internal routines (not fmgr-callable) */
  
  extern int	tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
