tcf03 has asked for the wisdom of the Perl Monks concerning the following question:

Can anyone explain the logic behind needing to subtract 86400 seconds from $modtime below to get a correct date?
code snippet below...
use POSIX qw(strftime); ... my $modtime = (stat($file))[9]; $modtime = $modtime - 86400; if ( $modtime == "" ) { $modtime = "null"; } else { $modtime = POSIX::strftime ("%B %d",$modtime,0,0,0,0,0,0,0,0); } ...

Replies are listed 'Best First'.
Re: questions about strftime
by thor (Priest) on Jan 10, 2005 at 21:38 UTC
    You needn't subtract anything. If you called strftime without doing so, it would work just fine. However, 86400 is the number of seconds in a day, so subtracting that amount from a time will give you 24 hours before that time. I don't know enough about what you're trying to do to know if that makes sense or not, though.

    thor

    Feel the white light, the light within
    Be your own disciple, fan the sparks of will
    For all of us waiting, your kingdom will come

      Here is the whole of it. Basically what it does is parses a file made by a login script each time a user logs in and matches it up with data from a a patchlink server (patchlink.com) running SQL server. It parses the data from these two sources and nags the users about PCs which have not logged onto our domain in 60 days and have also made no contact with the patchlink server. Its Kludgey - but its working, now Im working on cleaning up the code...
      # Script: OldAgents.pl # Find all old Patchlink Agents # TFiedler # We are dependant on these... use Win32::ODBC; use Win32::NetResource; use Win32::WinError; use POSIX qw(strftime); use Net::SMTP; # Connect to the udrive my %NetResource = ( LocalName => "U:", RemoteName => "\\\\SERVER\\share" ); my $User = "DOMAIN\\USER"; my $Password = "PASSWORD"; Win32::NetResource::AddConnection( \%NetResource, $Password, $User, 1 +); # If you are having problems connecting uncomment the following few li +nes and comment # out the line above... #if( Win32::NetResource::AddConnection( \%NetResource, $Password, $Use +r, 1 ) ) #{ # print "Successful\n"; #} #else #{ # print NetError(); #} # End connection to udrive routine... if ( -f "oldagents.txt" ) { print "Deleting old data file\n"; unlink("oldagents.txt"); print "Continuing...\n"; } else { print "Data file does not exist.\nContinuing...\n"; } open (OLDAGENTS,">oldagents.txt") || die "unable to open file c:\worki +ng\oldagents.txt\n"; # Lets calculate 60 days ago from NOW! # We are doing this in seconds. # The next 3 lines of code were gotten # from Perlmonks.org... my $thisday = time; my $SixtyDaysPrevious = $thisday - 60*24*60*60; $SixtyDaysPrevious = strftime "%m/%d/%Y", (localtime($SixtyDaysPreviou +s)); # End of perlmonks code. my $db = new Win32::ODBC( "DSN=patchlink_PLUS" ); # does this DB actually exist? if ( ! $db ) { die "Error connecting: " . Win32::ODBC::Error() . "\n"; } # YES! get the data... if ( $db->Sql ( "SELECT AgentName, LastContactDate, AgentVersion from +PLUS.dbo.UP_Agents where LastContactDate < '$SixtyDaysPrevious' order by LastContactDate" )) { # Ah you screwed UP! print "Error submitting SQL statement: " . $db->Error() . "\n"; } else { # Show me the money use Time::localtime; while( $db->FetchRow() ) { my @DATA=$db->Data ("AgentName", "LastContactDate", "AgentVers +ion"); my (undef, undef, $agent) = split(/\\/, $DATA[0]); # if you think you are getting bad data uncomment the # line below and watch the output. You should see # pcnames one per line w/o the \\ ie FIEDLER not \\FIEDLER # print "$agent\n"; my $file="u:\\usr\\NAV\\OS\\$agent\.txt"; # Added 12/07/04 (TF) if ( -f $file ) { open (PCFILE, "$file") || warn "Unable to open $agent.txt\ +n"; while (my @line = <PCFILE>) { foreach my $info(@line) { my (undef, $login, $os, $sp, $lc, $ie, $ip, undef) + = split(",",$info); my $modtime = (stat($file))[9]; $modtime = $modtime - 86400; if ( $modtime == "" ) { $modtime = "null"; } else { $modtime = POSIX::strftime ("%B %d",$modtime,0 +,0,0,0,0,0,0,0); #$modtime = POSIX::strftime ("%D",$modtime,0,0 +,0,0,0,0,0,0); } printf OLDAGENTS "Agent: %s\nAgent Version: %s\nLa +st Contact Date: %s\nUser: %s\nLast login: %s\nLast IP: %s\n\n", $DATA[0], $DATA[2], $DATA[1], $login, $modtime, $i +p; # NOW Lets NAG the user... open (LUSER, ">tmp/$agent.txt") || die "unable to +create $agent.txt\n"; printf LUSER "Agent: %s\nAgent Version: %s\nLast C +ontact Date: %s\nUser: %s\nLast in: %s\nLast IP: %s\n\n", $DATA[0], $DATA[2], $DATA[1], $login, $modtime, $i +p; close (LUSER); open (LUSER, "tmp/$agent.txt") || die "unable to o +pen $agent.txt\n"; $/=undef; # Sluuuuurp... while (my @EMAIL=<LUSER>) { $smtp=Net::SMTP->new('smtpserver.domain.com'); $smtp->mail( $ENV{USER} ); #$smtp->to('USER\@domain.com');# For testing $smtp->to("$login\@domain.com"); #$smtp->cc('USER2\@domain.com'); #$smtp->bcc('USER3\@domain.com'); $smtp->data(); $smtp->datasend("FROM: help\@domain.com\n"); $smtp->datasend("SUBJECT: PC name $agent\n"); $smtp->datasend("Below is a record of a PC tha +t was last logged into by you. This PC has not been\n"); $smtp->datasend("logged into the domain since +$modtime. If you use this PC occasionally,\n"); $smtp->datasend("please make sure that it is t +urned on for at least four hours per month. If you no\n"); $smtp->datasend("longer are in posession of th +is PC, please contact the help desk with the information\n"); $smtp->datasend("below. If you use this PC on +a regular basis please contact the help desk with the\n"); $smtp->datasend("information below.\n\nThank Y +ou\n\n"); foreach my $line(@EMAIL) { $smtp->datasend($line); } $smtp->dataend(); $smtp->quit; } #unlink ("tmp/$agent.txt"); } } } else { my $modtime = (stat($file))[9]; $modtime = $modtime - 86400; if ( $modtime == "" ) { $modtime = "null"; } else { $modtime = POSIX::strftime ("%B %d",$modtime,0,0,0,0,0 +,0,0,0); #$modtime = POSIX::strftime ("%F",$modtime,0,0,0,0,0,0 +,0,0); } printf OLDAGENTS "PC: %s\nAgent Version: %s\nLast Patchlin +k contact: %s\nLast domain login: %s\n\n", $DATA[0], $DATA[2], $DATA[1], $modtime; } } } close(OLDAGENTS); open (OLDAGENTS, "oldagents.txt") || die "unable to open oldagents.txt +\n"; $/=undef; # Sluuuuurp... while (@OLDA=<OLDAGENTS>) { $smtp=Net::SMTP->new('smtp.domain.com'); $smtp->mail( $ENV{USER} ); $smtp->to('USER1\@domain.com'); $smtp->cc('USER2\@domain.com'); $smtp->bcc('USER3\@domain.com'); $smtp->data(); $smtp->datasend("FROM: Patchlink\@Patchlink.domain.com\n"); $smtp->datasend("SUBJECT: Expired patchlink agents\n"); $smtp->datasend("Patchlink agents 60 days old or older:\n\n\n"); foreach $line(@OLDA) { $smtp->datasend($line); } $smtp->dataend(); $smtp->quit; } # Clean up... close(OLDAGENTS); # close open files $db->Close(); # close the DB Win32::NetResource::CancelConnection( "U:", 1, 1); # close the udrive! +!! # Subs sub NetError { my( $Error, $Text, $Provider ); $Error = Win32::GetLastError(); if( ERROR_EXTENDED_ERROR == $Error ) { Win32::NetResource::WNetGetLastError( $Error, $Text, $Provider + ); $Result = "Error: $Error: $Text (Genereated by $Provider)"; } else { $Text=Win32::FormatMessage( $Error ); $Result="Error: $Error: $Text"; } return $Result }
        This code is *ahem* interesting. Does it report the correct date/time in the e-mail? I don't see any reason to subtract a day's worth of seconds...seems arbitrary.

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

Re: questions about strftime
by gaal (Parson) on Jan 10, 2005 at 21:42 UTC
    86400 is one day's worth of seconds. You are looking at a time that is one day prior to this file's modification time.

    The condition in that if can never be true, by the way; and that call to POSIX::strftime, if it even works, is an ugly hack.

      I see your point about the if statement, thanks...
      the problem is when I look at the file (its ntfs) the date on the file is for arguments sake Jan 9, the day it is modified. When I run the above code against the file it always returns January 10 or 1 day more than the file modification time shown by windows.
Re: questions about strftime
by Zaxo (Archbishop) on Jan 11, 2005 at 05:44 UTC

    If you have servers in different time zomes, or with funny notions of time which somehow work out all right, you could call gmtime on the $modtime for accurate comparison. gmtime acts just like localtime, but produces UTC time.

    use POSIX 'strftime'; for (glob '*') { printf "%s\t%s\n", $_, strftime('%B %d', gmtime((stat)[9])); }

    In list context, gmtime and localtime both produce properly normalized time structs from epoch time.

    After Compline,
    Zaxo

Re: questions about strftime
by chromatic (Archbishop) on Jan 10, 2005 at 21:45 UTC

    I saved this snippet as a program and ran it on itself. It gave me January 10. Is your clock wrong?

      no the clock is fine, it works fine for me to on a Linux or BSD box, just in windows I need to subtract the 86400 from $modtime
        Are you using one local time on one machine and another time zone on one of the other machines? If, say you're in the US, Eastern Time Zone (GMT - 5 hours), an overlap could occur for 5 hours a day. e.g. 01:00 hours Tuesday GMT on one machine would be 20:00 hours Monday, EST on another. Just make sure all of the machines are on the same time zone.