Timezone Chooser

One of the things you need to do during a Linux installation is set the system's timezone. This page has a Perl script that provides time zone selection on a text console. It's useful for a customized Linux installation script, or as sample Perl script that does user interaction and traverses a directory structure.

Information for various time zones is kept in the filesystem, e.g., /usr/share/zoneinfo. The script allows the user to traverse this tree, find the desired time zone, and create a bash script (to run at boot time) that sets the system time zone to the user's selection in /etc/localtime.

The perl module Term-ANSIScreen is used for cursor addressing and text colors. It could be eliminated by coding the appropriate escape sequences.

Download a .zip file rather than copying the text below (trust me).

#!/usr/bin/perl -w # # # Copyright (c) 2007 DT Software Engineering, DTSEMAUI.COM # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. require 5.003 ; use lib '/usr/local/lib/perl5/site_perl/5.10.0/Term' ; use Config ; use strict ; use Term::ANSIScreen qw/:color :cursor :screen/; # To set the timezone, you make a symbolic link from the desired zone in /usr/share/zoneinfo # to /etc/localtime. my ( $zonenode, @zonelist, $zonefile, %dirflags, $rows, $row, $col, $zones, $reply ); my $level = 0; my $zonedir = "/usr/share/zoneinfo" ; # The directory where the resulting script is placed. #my $scriptdir = "/etc/" ; my $scriptdir = "./" ; my $scriptpath = $scriptdir . "my_tz_script.bash" ; sub get_answer() {    my $irow;    locate( $rows + 5 , 1 );    clline();    if ( $level > 0 ) {       print( "Enter Region or Zone ('<' to go up one level, '!' to quit): " ); }    else {       print( "Enter Region or Zone ('!' to quit): " ); }    chomp( $reply = ) ;    # Need to clear lines, in case next display doesn't overwrite them.    for ( $irow=$rows+5; $irow>0; $irow-- ) {       locate( $irow, 1 );       clline(); } } while ( 1 ) {    # Get the content of the current timezone directory into a list.    # Exclude *.tab files and .* files.    opendir( DIR, $zonedir ) or die "Cannot open timezone dir $zonedir: $!" ;    %dirflags = ( ) ;    @zonelist = ( ) ;    while ( $zonefile = readdir(DIR) ) {       next if ( $zonefile =~ /\S\.tab/ ) ;       next if ( $zonefile =~ /^\./ );       push @zonelist, $zonefile ;       $dirflags{$zonefile} = ( -d "$zonedir/$zonefile" ) ? 1:0 ; }    # Print the zone file (or directory) names.    @zonelist = sort @zonelist;    $zones = scalar @zonelist ;    $rows = int( $zones / 4 ) ;    for( $row=0; $row<=$rows; $row++ ) {       if ( $zones == 0 ) {          print( "\n" );          last; }       for( $col=0; $col<4; $col++ ) {          if ( $zones == 0 ) {             print( "\n" );             last; }          locate( $row+3, $col*20 );          $zonefile = shift @zonelist;          clline();          if ( $dirflags{$zonefile} == 1 ) {             print colored( $zonefile, "bold blue" ); }          else {             print( $zonefile ); }          $zones-- ; }    }    get_answer();    last if ( $reply eq "!" );    if ( $reply eq "<" ) {       # Up a level, if there is one.       if ( $level > 0 ) {          # Trim a node off the path.          $zonedir =~ s|/[-A-z_0-9]+$|| ;          $level--; }       } else {       #See if the input is valid.       if ( exists $dirflags{$reply} ) {          if ( $dirflags{$reply} == 1 ) {             # Choice is a directory so add to path expr and go there             $level++ ;             $zonedir = $zonedir."/".$reply; }       else {          # A leaf was chosen.          # Make a script to set the timezone to the selection.          if ( -e $scriptpath ) {             unlink $scriptpath ; }             open( TXSCR, ">".$scriptpath ) ;             printf TXSCR "if [ -f /etc/localtime ]; then mv /etc/localtime /etc/localtime~\n" ;             printf TXSCR "ln -s $zonedir /etc/localtime\n" ;             last; }       }    } }