On Fri, May 14, 2021 at 09:43:21PM -0400, John Hawkinson <jh...@alum.mit.edu> 
wrote:

> For what it's worth, I have a desire for the opposite kind of feature,
> although I don't quite know how it should work.
> I want to see and use timezones as displayed in messages as long as
> they are nearby US timezones that my brain is facile with the trivial
> arithmetic for (i.e. US/Eastern, US/Central, US/Pacific, and I suppose
> the rare US/Mountain).
> 
> But when a header comes in UTC, I'd much rather convert it to local
> time, especially so I don't have to think about how DST affects the
> offset.
> [...]
> --
> jh...@alum.mit.edu
> John Hawkinson

When my workplace switched to office365 (all but me anyway),
their emails started arriving with UTC date headers. So I
wrote a procmail recipe to filter incoming emails through
a little perl script to convert the date header to my timezone.
it's attached. the local timezone is hardcoded (sorry) but
can be changed as needed.

cheers,
raf

#!/usr/bin/env perl
use warnings;
use strict;

# procmail_filter_fix_outlook_date_header.pl
# 
# This is an email filter to be run by procmail as email arrives.
# It replaces UTC Date: headers in incoming email with the local timezone.
# Outlook/Exchange refuses to use the sender's local timezone in Date: headers.
# This can't recover the lost information about the true timezone of the
# sender, but at least you won't need to perform timezone calculations in
# your head when reading emails from your own work colleagues.
#
# usage (in ~/.procmailrc):
#
#     :0 fw
#     * ^From:.*@(domain_that_uses_exchange\.com|and_another\.com)
#     | procmail_filter_fix_outlook_date_header.pl
#
# WARNING: This is hard-coded to convert UTC to Australia/Sydney
# and needs to be modified if you are in a different timezone.
#
# 20200205 raf <r...@raf.org>

# Update these suit your local timezone.

my $local_tz = 'Australia/Sydney';             # Or `cat /etc/timezone` if present ($TZ didn't work for me)
my @local_offsets_by_dst = ('+1000', '+1100'); # How to get these programmatically?

use POSIX;

my %month_name2num = (Jan => 0, Feb => 1, Mar => 2, Apr => 3, May => 4, Jun => 5, Jul => 6, Aug => 7, Sep => 8, Oct => 9, Nov => 10, Dec => 11);
my %month_num2name = (0 => 'Jan', 1 => 'Feb', 2 => 'Mar', 3 => 'Apr', 4 => 'May', 5 => 'Jun', 6 => 'Jul', 7 => 'Aug', 8 => 'Sep', 9 => 'Oct', 10 => 'Nov', 11 => 'Dec');
my %day_num2name = (0 => 'Sun', 1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat');

while (<>)
{
	# Date: Tue, 4 Feb 2020 22:41:34 +0000
	my ($day, $month, $year, $hour, $minute, $second, $eol) = /^Date: (?:Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s+(\d{1,2})\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{4})\s+(\d{1,2}):(\d{2}):(\d{2}) \+0000(?:\s+\([A-Z]+\))?(\s*)$/;
	if (defined $day && defined $month && defined $year && defined $hour && defined $minute && defined $second)
	{
		print('X-Original-' . $_);
		local($ENV{TZ}) = 'UTC';
		my $t = mktime $second, $minute, $hour, $day, $month_name2num{$month}, $year - 1900;
		$ENV{TZ} = $local_tz;
		my ($sec, $min, $hr, $d, $m, $y, $wday, $yday, $isdst) = localtime($t);
		$_ = sprintf('Date: %s, %d %s %d %02d:%02d:%02d %s%s',
			$day_num2name{$wday}, $d, $month_num2name{$m}, @{[$y + 1900]},
			$hr, $min, $sec, $local_offsets_by_dst[$isdst], $eol);
	}
	print;
}

# vi:set ts=4 sw=4:

Reply via email to