Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
+++ protocols/nogaim.c	(revision 3e5766022e8103765d62343956cf1aeba34b4d82)
@@ -39,4 +39,5 @@
 
 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
+static char *format_timestamp( irc_t *irc, time_t msg_ts );
 
 GSList *connections;
@@ -718,5 +719,5 @@
 {
 	irc_t *irc = ic->irc;
-	char *wrapped;
+	char *wrapped, *ts;
 	user_t *u;
 	
@@ -760,8 +761,16 @@
 	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
 		strip_html( msg );
-
+	
+	if( ( ts = format_timestamp( irc, sent_at ) ) )
+	{
+		char *new = g_strconcat( ts, msg, NULL );
+		g_free( ts );
+		ts = msg = new;
+	}
+	
 	wrapped = word_wrap( msg, 425 );
 	irc_msgfrom( irc, u->nick, wrapped );
 	g_free( wrapped );
+	g_free( ts );
 }
 
@@ -867,5 +876,7 @@
 	if( c && u )
 	{
-		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped );
+		char *ts = format_timestamp( ic->irc, sent_at );
+		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
+		g_free( ts );
 	}
 	else
@@ -1061,6 +1072,92 @@
 }
 
-
-
+char *set_eval_timezone( set_t *set, char *value )
+{
+	char *s;
+	
+	if( strcmp( value, "local" ) == 0 ||
+	    strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
+		return value;
+	
+	/* Otherwise: +/- at the beginning optional, then one or more numbers,
+	   possibly followed by a colon and more numbers. Don't bother bound-
+	   checking them since users are free to shoot themselves in the foot. */
+	s = value;
+	if( *s == '+' || *s == '-' )
+		s ++;
+	
+	/* \d+ */
+	if( !isdigit( *s ) )
+		return SET_INVALID;
+	while( *s && isdigit( *s ) ) s ++;
+	
+	/* EOS? */
+	if( *s == '\0' )
+		return value;
+	
+	/* Otherwise, colon */
+	if( *s != ':' )
+		return SET_INVALID;
+	s ++;
+	
+	/* \d+ */
+	if( !isdigit( *s ) )
+		return SET_INVALID;
+	while( *s && isdigit( *s ) ) s ++;
+	
+	/* EOS */
+	return *s == '\0' ? value : SET_INVALID;
+}
+
+static char *format_timestamp( irc_t *irc, time_t msg_ts )
+{
+	time_t now_ts = time( NULL );
+	struct tm now, msg;
+	char *set;
+	
+	/* If the timestamp is <= 0 or less than a minute ago, discard it as
+	   it doesn't seem to add to much useful info and/or might be noise. */
+	if( msg_ts <= 0 || msg_ts > now_ts - 60 )
+		return NULL;
+	
+	set = set_getstr( &irc->set, "timezone" );
+	if( strcmp( set, "local" ) == 0 )
+	{
+		localtime_r( &now_ts, &now );
+		localtime_r( &msg_ts, &msg );
+	}
+	else
+	{
+		int hr, min = 0, sign = 60;
+		
+		if( set[0] == '-' )
+		{
+			sign *= -1;
+			set ++;
+		}
+		else if( set[0] == '+' )
+		{
+			set ++;
+		}
+		
+		if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
+		{
+			msg_ts += sign * ( hr * 60 + min );
+			now_ts += sign * ( hr * 60 + min );
+		}
+		
+		gmtime_r( &now_ts, &now );
+		gmtime_r( &msg_ts, &msg );
+	}
+	
+	if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
+		return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
+		                        msg.tm_hour, msg.tm_min, msg.tm_sec );
+	else
+		return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
+		                        "%02d:%02d:%02d\x02]\x02 ",
+		                        msg.tm_year + 1900, msg.tm_mon, msg.tm_mday,
+		                        msg.tm_hour, msg.tm_min, msg.tm_sec );
+}
 
 /* The plan is to not allow straight calls to prpl functions anymore, but do
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 7815a2b57887751a7e026747b27abea04b13abae)
+++ protocols/nogaim.h	(revision 3e5766022e8103765d62343956cf1aeba34b4d82)
@@ -324,4 +324,5 @@
 
 /* Misc. stuff */
+char *set_eval_timezone( set_t *set, char *value );
 char *set_eval_away_devoice( set_t *set, char *value );
 gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
