#! /usr/bin/perl -w # # Copyright (C) 2009 Oron Peled # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; use XML::SAX; my $mapfile; our $zoneinfo = '/usr/share/zoneinfo'; ($mapfile = shift) || die "Usage: $0 \n"; my $parser = XML::SAX::ParserFactory->parser( Handler => WindowsTzidHandler->new ); $parser->parse_uri("$mapfile"); exit 0; package WindowsTzidHandler; use base qw(XML::SAX::Base); sub start_document { my ($self, $doc) = @_; # process document start event #print "START_DOCUMENT\n"; } sub get_value { my $hash = shift || die; return $hash->{Value}; } sub get_attribute_value { my $elem = shift || die; my $name = shift || die; my $attr = $elem->{Attributes}; my %attr = %{$attr}; my $type; foreach my $k (sort keys %attr) { my $hash = $attr{$k}; if($hash->{LocalName} eq $name) { return get_value($hash); } } return undef; } my $inside_windows_mappping = 0; sub start_element { my ($self, $elem) = @_; my $localname = $elem->{LocalName}; if($localname eq 'mapTimezones') { my $type = get_attribute_value($elem, 'type'); die unless defined $type; $inside_windows_mappping = ($type eq 'windows') ? 1 : 0; } if($localname eq 'mapZone' && $inside_windows_mappping) { my $attr = $elem->{Attributes}; my %attr = %{$attr}; my $other = get_attribute_value($elem, 'other'); die unless defined $other; my $type = get_attribute_value($elem, 'type'); die unless defined $type; my $dest = "$main::zoneinfo/$type"; die "$0: Missing '$dest'\n" unless -e $dest; #printf "%s\t%s\n", $type, $other; symlink($type, $other) || die "$0: Failed symlink($type,$other): $!\n"; } } 1; =head1 NAME windows2tzid =head1 SYNOPSIS windows2tzid supplementalData.xml =head1 Description The windows2tzid program read an XML files used by UNICODE to describe the mapping from Windows(TM) time zone names to standard TZID names. The input file may be downloaded from: http://unicode.org/cldr/data/common/supplemental/supplementalData.xml Using this mapping information, the program creates symbolic links that map the Windows(TM) names to the correct TZID names used in the zoneinfo database. When the generated links are placed in the zoneinfo database (normally in /usr/share/zoneinfo), they can be used to resolve these names to the correct time zone data. This enables correct operation of applications that receive external data with Windows(TM) time zone information. An example use case, is receiving a meeting notification by mail and adding it to KDE korganizer -- without the generated symbolic links, the meeting would be inserted in the wrong time. =head1 AUTHOR Oron Peled