diff -Naur CalendarPlugin_20040301_start/lib/TWiki/Plugins/CalendarPlugin.pm CalendarPlugin_20040301_local/lib/TWiki/Plugins/CalendarPlugin.pm
--- CalendarPlugin_20040301_start/lib/TWiki/Plugins/CalendarPlugin.pm	Fri Apr  9 09:49:38 2004
+++ CalendarPlugin_20040301_local/lib/TWiki/Plugins/CalendarPlugin.pm	Mon Apr 19 10:02:47 2004
@@ -110,6 +110,9 @@
 	daynames			=> undef, # order is: Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday
 	topic			=> $topic,
 	web			=> $web,
+        gmtoffset               => undef,
+        tz                      => undef,
+        datenumberformat        => '$date$n',
 	format			=> "<a href=\"%SCRIPTURLPATH%/view%SCRIPTSUFFIX%/\$web/\$topic\"><font size=\"+2\">"
                                  . "\$old</font><img alt=\"\$description\" src=\"%PUBURLPATH%/$installWeb/CalendarPlugin/exclam.gif\" border=\"0\" /></a>"
     );
@@ -193,6 +196,49 @@
 }
 
 # =========================
+sub fetchDateParseDays
+{
+  if (defined $Date::Parse::VERSION) {
+    my( $refBullets,  %options) = @_;
+
+    my @localBullets = @{$refBullets};
+    @{$refBullets} = ();
+    my @res;
+
+    foreach my $bullet ( @localBullets ) {
+      my ($timedescr) = ( $bullet =~ /^\s+\*\s([^|]*)/ );
+      my @timedescr = split "-", $timedescr;
+      my $text = pop @timedescr;
+      my $date1 = join "-", @timedescr;
+      my ($ss1,$mm1,$hh1,$day1,$month1,$year1,$zone1) = &Date::Parse::strptime ( $date1 );
+      # minimal requirements are a valid hour and minute
+      if (
+	  (defined $hh1)
+	  and
+	  (defined $mm1)
+	 ) {
+	# Fixup time to match conventions of HTML::CalendarMonthSimple
+	$month1++;
+	$year1+=1900 if (defined $year1);
+	# Correct for timezone of requested calendar
+	my $zone2 = $options{gmtoffset};
+	$zone2 = $zone2 * 3600;
+	my $offset = -$zone1+$zone2;
+	($year1, $month1, $day1, $hh1, $mm1, $ss1) = Add_Delta_YMDHMS(
+								    $year1, $month1, $day1, $hh1, $mm1, $ss1,
+								    0, 0, 0, 0, 0, $offset);
+	# valid
+	push @res, [$ss1,$mm1,$hh1,$day1,$month1,$year1,$text];
+      } else {
+	# not valid, leave it on the list of possible events
+	push @{$refBullets}, $bullet;
+      }
+    }
+    return @res;
+  }
+}
+
+# =========================
 sub emptyxmap {
 	use Date::Calc qw( Days_in_Month );
 	($y, $m) = @_;
@@ -241,12 +287,13 @@
 {
     my( $attributes, $refText, $theTopic, $theWeb ) = @_;
 
-    use Date::Calc qw( Date_to_Days Days_in_Month Day_of_Week Nth_Weekday_of_Month_Year Add_Delta_Days Today_and_Now Add_Delta_YMDHMS Today);
+    use Date::Calc qw( Date_to_Days Days_in_Month Day_of_Week Nth_Weekday_of_Month_Year Add_Delta_Days Today_and_Now Add_Delta_YMDHMS Today Month_to_Text);
 
     # lazy load of needed libraries
     if (   $libsError  ) { return "";  }
     if ( ! $libsLoaded ) {
 	eval 'require HTML::CalendarMonthSimple';
+	eval 'require Date::Parse';
 	if ( defined( $HTML::CalendarMonthSimple::VERSION ) ) {
 	    $libsLoaded = 1;
 	} else	{
@@ -273,13 +320,17 @@
     # read and set the desired language
     my $lang = scalar &TWiki::Func::extractNameValuePair( $attributes, "lang" );
     Date::Calc::Language(Date::Calc::Decode_Language($lang)) if $lang;
-    
+
     # get GMT offset
     my ($currentYear, $currentMonth, $currentDay, $currentHour, $currentMinute, $currentSecond) = Today_and_Now(1);
-    my $gmtoff = scalar &TWiki::Func::extractNameValuePair( $attributes, "gmtoffset" );
-    if ( $gmtoff ) {
-    	$gmtoff += 0;
-    	($currentYear, $currentMonth, $currentDay, $currentHour, $currentMinute, $currentSecond) = Add_Delta_YMDHMS($currentYear, $currentMonth, $currentDay, $currentHour, $currentMinute, $currentSecond, 0, 0, 0, $gmtoff, 0, 0);
+
+    my ($tzoff) = ($options{tz} =~ /GMT(.*)/);
+
+    &TWiki::Func::writeDebug("options{gmtoffset} = $gmtoff | $tzoff | 0");
+    $options{gmtoffset} = $tzoff || $options{gmtoffset} || 0;
+
+    if ( $options{gmtoffset} ) {
+    	($currentYear, $currentMonth, $currentDay, $currentHour, $currentMinute, $currentSecond) = Add_Delta_YMDHMS($currentYear, $currentMonth, $currentDay, $currentHour, $currentMinute, $currentSecond, 0, 0, 0, $options{gmtoffset}, 0, 0);
     }
 	
     # handle relative dates, too  #cs#
@@ -301,6 +352,12 @@
        $cal->weekdays(map { Date::Calc::Day_of_Week_to_Text $_ } (1..5));
     }
 
+    # Header value substitution
+    $options{header} =~ s/\$month/&Month_to_Text($m)/ge ;
+    $options{header} =~ s/\$year/$y/g ;
+    $options{header} =~ s/\$tz/$options{gmtoffset}/g ;
+    $options{header} =~ s/\$gmtoffset/$options{gmtoffset}/g ;
+
     my $p = "";
     while (($k,$v) = each %options) {
 	$p = "HTML::CalendarMonthSimple::$k";
@@ -317,7 +374,10 @@
     # set the initial day values if normal date numbers are not shown
     if ($cal->showdatenumbers == 0) {
 	for ($i=1; $i<33 ; $i++) {
-	    $cal->setcontent($i,"$i");
+	  my $format = $options{datenumberformat};
+	  $format =~ s/\$date/$i/g ;
+	  $format =~ s/\$n/\n/g ;
+	  $cal->setcontent($i,"$format");
 	}
     }
 
@@ -379,7 +439,7 @@
             my $date = Date_to_Days ($y, $m, $d);
             if ($date1 <= $date && $date <= $date2) {
                 if ($xmap[$d]) {
-                    &highlightDay( $cal, $d, $descr, %options);
+                    &highlightDay( $cal, $d, undef, $descr, %options);
                 }
             }
         }
@@ -398,7 +458,7 @@
         for my $d (1 .. Days_in_Month ($y, $m)) {
             my $date = Date_to_Days ($y, $m, $d);
             if ($date1 <= $date && $date <= $date2 && $xmap[$d]) {
-                &highlightDay( $cal, $d, $descr, %options);
+                &highlightDay( $cal, $d, undef, $descr, %options);
             }
         }
     }
@@ -407,7 +467,7 @@
     foreach $d (@days) {
         ($dd, $mm, $yy, $xs, $xcstr, $descr) = split( /\|/, $d);
         if ($yy == $y && $months{$mm} == $m) {
-            &highlightDay( $cal, $dd, $descr, %options);
+            &highlightDay( $cal, $dd, undef, $descr, %options);
         }
     }
     # then collect all dates without year
@@ -420,7 +480,7 @@
             @xmap = &emptyxmap($y, $m);
         }
         if ($months{$mm} == $m && $xmap[$dd]) {
-            &highlightDay( $cal, $dd, $descr, %options );
+            &highlightDay( $cal, $dd, undef, $descr, %options );
         }
     }
     
@@ -435,7 +495,7 @@
         }
         $hd = Nth_Weekday_of_Month_Year($y, $m, $wdays{$dd}, $nn);
     	if ($hd <= Days_in_Month($y, $m) && $xmap[$hd]) {
-            &highlightDay( $cal, $hd, $descr, %options );
+            &highlightDay( $cal, $hd, undef, $descr, %options );
         }
     }
 
@@ -451,7 +511,7 @@
         $hd = Nth_Weekday_of_Month_Year($y, $m, $wdays{$dd}, 1);
         do {
             if ($xmap[$hd]) {
-                &highlightDay( $cal, $hd, $descr, %options );
+                &highlightDay( $cal, $hd, undef, $descr, %options );
             }
             ($ny, $nm, $hd) = Add_Delta_Days($y, $m, $hd, 7);
         } while ($ny == $y && $nm == $m);
@@ -478,7 +538,7 @@
                 $hd = Nth_Weekday_of_Month_Year($y, $m, $wdays{$dy}, $dd);
             }
             if ($xmap[$hd]) {
-                &highlightDay( $cal, $hd, $descr, %options );
+                &highlightDay( $cal, $hd, undef, $descr, %options );
             }
         }
     }
@@ -499,7 +559,7 @@
             }
             do {
                 if ($xmap[$dd]) {
-                    &highlightDay( $cal, $dd, $descr, %options );
+                    &highlightDay( $cal, $dd, undef, $descr, %options );
                 }
                 ($yy, $mm, $dd) = Add_Delta_Days($yy, $mm, $dd, $p);
             } while ($yy == $y && $mm == $m);
@@ -516,10 +576,29 @@
             @xmap = &emptyxmap($y, $m);
         }
         if ($dd > 0 && $dd <= Days_in_Month($y, $m) && $xmap[$dd]) {
-            &highlightDay( $cal, $dd, $descr, %options );
+            &highlightDay( $cal, $dd, undef, $descr, %options );
         }
     }
 
+    # Use Date::Parse for date/time pairs
+    @days = fetchDateParseDays( \@bullets, %options );
+    my %highlight;
+    foreach $d (@days) {
+      my ($ss1,$mm1,$hh1,$day1,$month1,$year1,$descr) = @{$d};
+      if ($year1 == $y && $month1 == $m) {
+	push @{$highlight{$day1}{sprintf("%02d:%02d",$hh1,$mm1)}}, $descr;
+      }
+    }
+
+    # Highlight the days in time order
+    foreach $d ( sort keys %highlight ) {
+      foreach my $time ( sort keys %{$highlight{$d}} ) {
+	foreach my $ev ( sort @{$highlight{$d}{$time}} ) {
+ 	  &highlightDay( $cal, $d, $time, $ev, %options);
+	}
+      }
+    }
+
     return $cal->as_HTML;
 }
 
@@ -566,13 +645,14 @@
 
 sub highlightDay
 {
-	my ($c, $day, $description, %options) = @_;
+	my ($c, $day, $time, $description, %options) = @_;
 	my $old = $c->getcontent($day);
 	my $format = $options{format};
 	$format =~ s/\$description/$description/g ;
 	$format =~ s/\$web/$options{web}/g ;
 	$format =~ s/\$topic/$options{topic}/g ;
 	$format =~ s/\$day/$day/g ;
+	$format =~ s/\$time/$time/g ;
 	$format =~ s/\$old/$old/g ;
 	$format =~ s/\$installWeb/$installWeb/g ;
 	$format =~ s/\$n/\n/g ;
