root/postprocessors/augment_timezone @ 680

Revision 680, 7.3 kB (checked in by max, 6 years ago)

Added Shepherd::MythTV for interaction with MythTV database
Migrated augment_timezone postprocessor to use it

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl -w
2
3# Augment XMLTV start/stop times with the local timezone if MythTV's
4# TimeOffset setting is anything other than "None"
5#  * to be used as a postprocessor for XMLTV data
6#  * can be used in conjunction with 'shepherd' XMLTV reconciler or standalone
7#    (pipe-through)
8#  * no configuration necessary
9#
10#  input XMLTV files will either have programme start/stop with or without
11#  timezones.  If no timezone is present, Shepherd assumes the input
12#  start/stop times are in 'localtime'.
13#
14#  If MythTV's "TimeOffset" setting is set to anything other than 'None',
15#  this can cause programming information to be out:
16#   - if set to 'All', all programs will be out by the difference between
17#     GMT and locatime ('All' means MythTV is expecting all start/stop times
18#     in GMT)
19#   - if explicitly set to GMT +/- XX then this will cause programming to
20#     be out whenever there is a switchover to/from daylight savings
21#
22#  this postprocessor addresses this by explicitly putting a timezone
23#  on every programme that doesn't already have one, BUT ONLY IF
24#  MythTV is configured to anything other than 'None'.
25#
26#  provided your unix system is configured into the correct timezone,
27#  this will work just fine including boundaries crossing daylight savings.
28#
29#  it means that it doesn't matter if MythTV's "TimeOffset" is set to
30#  'All' or 'None', or something inbetween, the data will be right regardless.
31
32use strict;
33my $progname = "augment_timezone";
34my $version = "0.13";
35
36use XMLTV;
37use POSIX qw(strftime mktime);
38use Getopt::Long;
39use IO::File;
40use Shepherd::MythTV;
41
42$| = 1;
43my %stats;
44
45my $opt = { };
46$opt->{output_file} =   "output.xmltv";
47$opt->{debug} =                 0;
48
49# parse command line
50GetOptions(
51        'output=s'              => \$opt->{output_file},
52        'mysql_file=s'          => \$opt->{mysql_file},
53        'timeoffset=s'          => \$opt->{timeoffset},
54
55        'region=i'              => \$opt->{region},             # ignored
56        'days=i'                => \$opt->{days},               # ignored
57        'offset=i'              => \$opt->{offset},             # ignored
58        'timezone=s'            => \$opt->{timezone},           # ignored
59        'channels_file=s'       => \$opt->{channels_file},      # ignored
60        'config-file=s'         => \$opt->{configfile},         # ignored
61
62        'help'                  => \$opt->{help},
63        'verbose'               => \$opt->{help},
64        'version'               => \$opt->{version},
65        'ready'                 => \$opt->{ready},
66        'desc'                  => \$opt->{desc},
67        'v'                     => \$opt->{version});
68
69printf "%s v%s\n",$progname,$version;
70
71if ($opt->{version} || $opt->{desc} || $opt->{help} || $opt->{ready} ||
72    $opt->{output_file} eq "") {
73        printf "Automatically adjust the XMLTV start/stop timezone based on MythTV's\n".
74            "TImeOffset setting.\n" if $opt->{desc};
75
76        printf "$progname is ready for operation.\n" if ($opt->{ready});
77
78        printf "No --output file specified.\n" if ($opt->{output_file} eq "");
79
80        if ($opt->{help} || $opt->{output_file} eq "") {
81                my $default_loc = &Shepherd::MythTV::standard_mysql_locations;
82                print<<EOF
83
84usage: $0 [options] {FILE(s)}
85
86Supported options include:
87  --output={file}      Send final XMLTV output to {file} (default: $opt->{output_file})
88  --mysql_file={file}  File where we look for mythtv database user/pass/dbi (default: $default_loc)
89  --timeoffset={s}     Specify MythTV's setting, rather than try to look it up
90                       in MythTV's database. (E.g. "Auto", "None", "+1000")
91
92EOF
93;
94        }
95        exit(0);
96}
97
98unless ($opt->{timeoffset}) {
99        # Specify a non-standard location for mysql.txt
100        Shepherd::MythTV::setup($opt->{mysql_file}) if ($opt->{mysql_file});
101
102        my $sql = "SELECT data FROM settings WHERE value LIKE 'TimeOffset'";
103        ($opt->{timeoffset}) = Shepherd::MythTV::query($sql);
104        unless ($opt->{timeoffset}) {
105                print "         Won't augment any timezones!\n" .
106                      "         Assuming MythTV's timezone is \"None\".\n".
107                      "         *** If this is wrong, guide data may be in wrong timezone! ***\n\n";
108        }
109}
110
111$opt->{timeoffset} = "None" if (!defined $opt->{timeoffset});
112if ($opt->{timeoffset} eq "None") {
113        print " - MythTV's TimeOffset setting is set to \"None\". No need to do anything.\n";
114} else {
115        printf " - MythTV's TimeOffset setting is set to \"%s\". Adding timezones.\n",$opt->{timeoffset};
116}
117
118my %writer_args = ( encoding => 'ISO-8859-1' );
119my $fh = new IO::File(">".$opt->{output_file}) || die "can't open $opt->{output_file} for writing: $!";
120$writer_args{OUTPUT} = $fh;
121
122my $writer = new XMLTV::Writer(%writer_args);
123$writer->start( {
124        'source-info-name' => "$progname $version",
125        'generator-info-name' => "$progname $version"} );
126
127foreach my $file (@ARGV) {
128        printf " - parsing: %s\n", ($file eq "-" ? "(from-stdin, hit control-D to finish)" : $file);
129        XMLTV::parsefiles_callback(undef, undef, \&channel_cb,\&programme_cb, $file);
130}
131
132$writer->end();
133
134printf "Finished parsing, output in $opt->{output_file}\n";
135printf "STATS: TimeOffset=".$opt->{timeoffset};
136foreach my $k (keys %stats) {
137        printf ", %d %s", $stats{$k}, $k;
138}
139printf "\n";
140
141exit(0);
142
143##############################################################################
144
145sub channel_cb( $ )
146{
147        my $c = shift;
148        # printf "got channel ".Dumper($c);
149        $writer->write_channel($c);
150}
151
152##############################################################################
153
154sub programme_cb( $ )
155{
156        my $prog=shift;
157
158        if ($opt->{timeoffset} ne "None") {
159                # if there is no timezone present in start time, put one there
160                if (($prog->{start} !~ /\+/) && ($prog->{start} !~ /\-/)) {
161                        $prog->{start} = POSIX::strftime("%Y%m%d%H%M00 %z",localtime(parse_xmltv_date($prog->{start})));
162                        $stats{start_tz_added}++;
163                }
164
165                # if there is no timezone present in stop time, put one there
166                if (($prog->{stop} !~ /\+/) && ($prog->{stop} !~ /\-/)) {
167                        $prog->{stop} = POSIX::strftime("%Y%m%d%H%M00 %z",localtime(parse_xmltv_date($prog->{stop})));
168                        $stats{stop_tz_added}++;
169                }
170        }
171
172        $writer->write_programme($prog);
173}
174
175##############################################################################
176
177# strptime type date parsing - BUT - if no timezone is present, treat time
178# as being in localtime rather than the various other perl implementation
179# which treat it as being in UTC/GMT
180
181sub parse_xmltv_date
182{
183        my $datestring = shift;
184        my @t; # 0=sec,1=min,2=hour,3=day,4=month,5=year,6=wday,7=yday,8=isdst
185        my $tz_offset = 0;
186
187        if ($datestring =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/) {
188                ($t[5],$t[4],$t[3],$t[2],$t[1],$t[0]) = (int($1)-1900,int($2)-1,int($3),int($4),int($5),0);
189                ($t[6],$t[7],$t[8]) = (-1,-1,-1);
190
191                my $e = mktime(@t);
192
193                # if input data has a timezone offset, then offset by that
194                if ($datestring =~ /\+(\d{2})(\d{2})/) {
195                        $tz_offset = calc_gmt_offset($e) - (($1*(60*60)) + ($2*60));
196                } elsif ($datestring =~ /\-(\d{2})(\d{2})/) {
197                        $tz_offset = calc_gmt_offset($e) + (($1*(60*60)) + ($2*60));
198                }
199
200                return ($e+$tz_offset) if ($e > 1);
201        }
202        return undef;
203}
204
205##############################################################################
206
207# given a particular date (in epoch time), return the local timezone offset
208# on that date in -/+ seconds from GMT
209
210sub calc_gmt_offset
211{
212        my $e = shift;
213        my $gmt_offset;
214
215        my $tzstring = strftime("%z", localtime($e));
216        $gmt_offset = (60*60) * int(substr($tzstring,1,2));     # hr
217        $gmt_offset += (60 * int(substr($tzstring,3,2)));       # min
218        $gmt_offset *= -1 if (substr($tzstring,0,1) eq "-");    # +/-
219
220        return $gmt_offset;
221}
Note: See TracBrowser for help on using the browser.