[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[mhc:00029] Re: 1.94b23
On Tue, 18 May 1999 14:59:29 +0900,
OHARA Shigeki <os@xxxxxxxxx> said:
> > > #--date=("today"|"tomorrow"|yy/mm/dd)
> > なるほど。情報工学演習でも聞きながらでもやってみましょう。
これを実装しました。--date=(today|tomorrow|yyyymmdd)
の引数を取ります。--today=yes も一応残してあります。
> まだ仕様も決まってないですが、
> 勝手にこれに合わせて today をいじってみました。
ども。ばっちり動いています。:-)
--
nom
#!/usr/local/bin/perl
##
## $Id: mscan2,v 1.9 1999/05/18 06:02:32 nom Exp $
##
## X-SC-* Header Spec:
##
## {Month} : (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
## {Order} : (1st|2nd|3rd|4th|Last)
## {Week} : (Sun|Mon|Tue|Wed|Thu|Fri|Sat)
## {DayNo} : 1-31
## {Date} : !?yyyymmdd
## {Duration}: yyyymmdd-yyyymmdd
## {Time} : (none|HH:MM-HH:MM|HH:MM)
## {Keyword} : \S+
##
## X-SC-Subject: English Exam # {String}
## X-SC-Category: Todo Holiday # list of {Keyword}
## X-SC-Location: S114 # {Keyword}
## X-SC-Day: 19960508 !19960509 # list of {Date}
## X-SC-Time: 11:00-12:00 # {Time}
## X-SC-Cond: 2nd Wed # list of {Month}|{Order}|{Week}|{DayNo}
## X-SC-Duration: 19960501-19970331 # {Duration}
##
## X-SC-Date: 5 Apr 99 18:00 # for backward compatibility.
##
##
##
################################################################
### Global variables.
###
$NKF = "nkf";
$SCAN = "imls";
$USER = $ENV{'USERNAME'} || $ENV{'USER'} || $ENV{'LOGNAME'};
$HOME = $ENV{'HOME'};
$MailDir = "$HOME/Mail";
$rootFolder = "schedule";
$ScheduleDir = "$MailDir/$rootFolder";
$dot_schedule = "$HOME/.schedule";
$intersect = "intersect";
$dot_schedule = "$HOME/.schedule";
################################################################
### set options.
###
## --src=+ (+inbox)
## --squeeze=on/off (off)
## --today=on/off (off)
## --nonum=on/off (off)
## --virtual=on/off (on)
## --schedule=on/off (off)
$virtualFLG = 1;
foreach (@ARGV){
if (/^--squeeze=(.*)$/){
$squeezeFLG = on_off($1);
$scheduleFLG = 1;
}elsif (/^--today=(.*)$/){
$dateFLG = on_off($1);
$dateString = get_date_string('today');
$scheduleFLG = 1;
}elsif (/^--date=(today|tomorrow|\d{8})$/){
$dateFLG = 1;
$dateString = get_date_string($1);
$scheduleFLG = 1;
}elsif (/^--nonum=(.*)$/){
$nonumFLG = on_off($1);
$scheduleFLG = 1;
}elsif (/^\+$rootFolder\/\d\d\d\d\/\d\d/){
$scFolder = $_;
$scheduleFLG = 1;
}elsif (/^--src=(\+$rootFolder\/\d\d\d\d\/\d\d)$/){
$scFolder = $1;
$scheduleFLG = 1;
}else {
}
}
$squeezeFLG = ($squeezeFLG | $dateFLG);
$nonumFLG = ($nonumFLG | $squeezeFLG | $dateFLG);
$virtualFLG = !$nonumFLG;
##
## convert a datekeyword to corresponding 'yyyy/mm/dd'
## datekeyword: today, tomorrow, yyyymmdd
##
sub get_date_string
{
my $str = shift;
my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
$mon++; $year += 1900;
if ($str eq 'today'){
} elsif ($str eq 'tomorrow'){
($sec, $min, $hour, $day, $mon, $year) = localtime(time + 60*60*24);
$mon++; $year += 1900;
} elsif ($str =~ /^(\d\d\d\d)(\d\d)(\d\d)$/){
($year, $mon, $day) = ($1||$year, $2||$mon, $3);
} else {
return undef;
}
return sprintf("%04d/%02d/%02d", $year, $mon, $day);
}
sub on_off
{
my $p = shift;
return $p =~ /^(on|yes)$/i ? 1 : 0;
}
################################################################
### main
###
if (!$scFolder && !$dateString){
($sec, $min, $hour, $day, $mon, $year) = localtime(time);
$mon++; $year += 1900;
$scFolder = sprintf("+$rootFolder/%04d/%02d", $year, $mon);
} elsif (!$scFolder && $dateString){
$scFolder = "+$rootFolder/" . substr($dateString, 0, -3);
} elsif ($scFolder && !$dateString){
## nothing is done
} elsif ($scFolder && $dateString){
if (substr($scFolder, -7) ne substr($dateString, 0, -3)){
die("--src=+xxx and --date=yyyymmdd is incompatible.\n");
}
}
# make source dir -- strip first '+' char from $scFolder, and
# concatinate with $MailDir.
$scDir = sprintf("%s/%s", $MailDir, substr($scFolder, 1));
($year, $mon) = ($scDir =~ m!/(\d\d\d\d)/(\d\d)$!);
## if argument doesn't have '+schddule/...' nor '-month', scan normally.
if (!$scheduleFLG){
exec ("$SCAN", @ARGV) || die "Can't exec $SCAN.\n";
}
open(STDOUT, "| $NKF -j");
new();
@nth = ('1st', '2nd', '3rd', '4th', 'Last');
@week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
@week2 = ('(Sun)', ' Mon ', ' Tue ', ' Wed ', ' Thu ', ' Fri ', ' Sat ');
@month = ('Jan', 'Feb', 'Mar', 'Apr',
'May', 'Jun', 'Jul', 'Aug',
'Sep', 'Oct', 'Nov', 'Dec',
);
scanMonth($mon, $year);
close(STDOUT);
exit 0;
################################################################
### Scan function
###
sub scanMonth # ($mon, $year)
{
my ($mon, $year) = @_;
my $dDate = $year * 10000 + $mon * 100 + 1;
my $daysOfMonth = daysOfMonth($mon, $year);
my $week = dayOfWeek($mon, 1, $year);
my $M = $month[$mon - 1];
for ($day = 1; $day <= $daysOfMonth; $day++, $dDate++, $week++){
my $W = $week[$week % 7];
my @TMP = ScheduleItem::search($dDate, $M, $daysOfMonth, $W, $day);
next if ($dateFLG && $day != substr($dateString, -2));
$number = 0;
if (@TMP){
$first = 1;
foreach (sort { $a->{'startTime'} cmp $b->{'startTime'};} @TMP) {
if ($nonumFLG){
$number = "";
} else {
$number = sprintf("%4d | ", $_->{'fileno'});
}
if ($first){
printf($number . "%02d/%02d %4s ", $mon,
$day, $week2[$week % 7]);
} else {
printf($number . " ");
}
printf("%5s ", $_->{'startTime'});
if ($virtualFLG) {
$n = $_->{'fileno'} || 0;
print "$_->{'subject'} \r $_->{'folder'} $n\n";
} else {
print "$_->{'subject'}\n";
}
$first = 0;
}
} elsif (! $squeezeFLG){
if ($nonumFLG){
$number = "";
} else {
$number = sprintf("%4d | ", 0);
}
printf($number . "%02d/%02d %4s \r $scFolder 0\n",
$mon, $day, $week2[$week % 7]) if $virtualFLG;
printf($number . "%02d/%02d %4s\n",
$mon, $day, $week2[$week % 7]) if !$virtualFLG;
}
}
}
################################################################
### Read all schedule files, Create schedule item objects.
###
sub new
{
my %header;
my $folder;
my $tag;
my $no = 0;
my @Schedule;
open(SCHEDULE, "$dot_schedule");
while (<SCHEDULE>) {
if (/^$/) {
$Schedule[$no++] = ScheduleItem->new(%header);
undef %header;
} elsif (/^x-sc-([^:]+):\s*(\S.*)/i) {
$tag = $1;
$tag =~ tr [A-Z] [a-z];
$header{$tag} = $2;
} elsif (/^\s+(.*)/){
$header{$tag} .= " $1";
}
}
close(SCHEDULE);
foreach (<$scDir/[0-9]*>, <$ScheduleDir/$intersect/[0-9]*>){
last if (! -f $_);
open(FILE, $_) || die;
($filename) = m|([^/]+)$|;
($folder) = m|^$MailDir/(.*)/\d+$|;
$folder = '+' . $folder;
# print "OPEN $_ ($folder $filename)\n";
while (<FILE>){
if (/^$/) {
correct_header(\%header);
$header{'fileno'} = $filename;
$header{'folder'} = $folder;
$Schedule[$no++] = ScheduleItem->new(%header);
undef %header;
close(FILE);
next;
} elsif (/^x-sc-([^:]+):\s*(\S.*)/i) {
$tag = $1;
$tag =~ tr [A-Z] [a-z];
$header{$tag} = $2;
}
}
}
if (defined %header){
$Schedule[$no++] = ScheduleItem->new(%header);
}
return bless \@Schedule;
}
##
## For backward compatibility.
##
sub correct_header
{
my $header = shift;
my ($day, $mon, $year, $time);
if (
#!defined $header->{'day'} &&
$header->{'date'} =~ /(\d+)\s+([A-Z][a-z][a-z])\s+(\d+)\s(\d\d:\d\d)/
){
($day, $mon, $year, $time) = ($1, $2, $3, $4);
$mon = index("JanFebMarAprMayJunJulAugSepOctNovDec", $mon) / 3 + 1;
$year += 1900 if ($year < 100);
# print "X-SC-Date: $header->{'date'}\n";
$header->{'day'} = sprintf("%04d%02d%02d", $year, $mon, $day);
$header->{'startTime'} = $time if ($time ne "00:00");
# print "X-SC-Day: $header->{'day'}\n";
# print "X-SC-Time: $header->{'time'}\n";
}
}
######################################
package ScheduleItem;
######################################
################################################################
### Schedule Item Object Mangement.
###
## スケジュール情報を格納している hash tree の構造
##
## ROOT -> YYYYMMDD -> PointerToEventList
## ROOT -> Month -> DayNo -> PointerToEventList
## ROOT -> Month -> Order -> Week -> PointerToEventList
## ROOT -> !YYYYMMDD -> PointerToEventList
##
$TREE = {};
sub new
{
shift;
my %headers = @_;
my (@cond, @month, @order, @week, @dayno);
my ( $month, $order, $week, $dayno);
my $DEBUG = 0;
my $fourthFlag;
my $lastFlag;
if ($headers{'time'}){
($headers{'startTime'}, $headers{'endTime'})
= split(/-/, $headers{'time'});
}
if ($headers{'day'}) {
@date = split(/\s+/, $headers{'day'});
foreach (@date) {
push(@{$TREE->{$_}}, \%headers);
print "$_ is $headers{'subject'}\n" if $DEBUG;
}
}
if ($headers{'cond'}) {
@cond = split(/\s+/, $headers{'cond'});
foreach (@cond) {
if (/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/) {
push(@month, $1);
} elsif (/(Sun|Mon|Tue|Wed|Thu|Fri|Sat)/) {
push(@week, $1);
} elsif (/(1st|2nd|3rd)/){
push(@order, $1);
} elsif (/4th/) {
$fourthFlag = 1;
} elsif (/Last/) {
$lastFlag = 1;
} elsif (/(\d+)/) {
push(@dayno, $1);
}
}
if ($fourthFlag && $lastFlag){
push(@order, '4thLast');
} elsif ($fourthFlag) {
push(@order, '4th');
} elsif ($lastFlag) {
push(@order, 'Last');
}
@month = ('All') if (!@month);
@order = ('All') if (!@order);
foreach $month (@month) {
foreach $order (@order) {
foreach $week (@week) {
push(@{$TREE->{$month}->{$order}->{$week}}, \%headers);
print "$month $order $week is $headers{'subject'}\n"
if $DEBUG;
}
}
foreach $dayno (@dayno) {
push(@{$TREE->{$month}->{$dayno}}, \%headers);
print "$month $dayno is $headers{'subject'}\n"
if $DEBUG;
}
}
}
if ($headers{'duration'}){
($headers{'startDate'}, $headers{'endDate'})
= split(/-/, $headers{'duration'});
}
}
sub search # (yyyymmdd, mon, daysOfMonth, week, dayno)
{
my @nth = ('1st', '2nd', '3rd', '4th', 'Last');
my ($yymmdd, $month, $daysOfMonth, $week, $dayno) = @_;
my @ret;
my $x;
my $order = $nth[($dayno - 1) / 7];
my @items;
if ($dayno + 7 > $daysOfMonth && $dayno < 29) {
# この日は、4th かつ、Last
@items =
(
@{$TREE->{$yymmdd}},
@{$TREE->{$month}->{$order}->{$week}},
@{$TREE->{$month}->{'Last'}->{$week}},
@{$TREE->{$month}->{'All' }->{$week}},
@{$TREE->{'All' }->{$order}->{$week}},
@{$TREE->{'All' }->{'Last'}->{$week}},
@{$TREE->{'All' }->{'All'}->{$week}},
@{$TREE->{$month}->{$dayno}},
@{$TREE->{'All' }->{$dayno}},
);
} else {
@items =
(
@{$TREE->{$yymmdd}},
@{$TREE->{$month}->{$order}->{$week}},
@{$TREE->{$month}->{'All'}->{$week}},
@{$TREE->{'All'}->{$order}->{$week}},
@{$TREE->{'All'}->{'All'}->{$week}},
@{$TREE->{$month}->{$dayno}},
@{$TREE->{'All'}->{$dayno}},
);
}
foreach $x (@items){
push(@ret, $x) if ((!defined $TREE->{"!$yymmdd"} ||
!grep($x eq $_, @{$TREE->{"!$yymmdd"}}))
&&
(!defined($x->{'duration'}) ||
($yymmdd >= $x->{'startDate'} &&
$yymmdd <= $x->{'endDate'})));
}
return @ret;
}
################################################################
### Date calculation routines.
###
######################################
package main;
######################################
# isLeapYear(int year) -- check if leap year
#
# year:
# ex. 1994
# return:
# 1 ... leap year
# 0 ... not leap year
#
sub isLeapYear
{
my ($year) = @_;
return 1 if ($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0;
return 0;
}
# dayOfYear(int mon, int day, int year) -- Nth day of the year.
#
# mon, day, year:
# ex. 7, 1, 1994
# return:
# 182 ... 7, 1, 1994 is the 182nd day of the year.
#
sub dayOfYear
{
my ($mon, $day, $year) = @_;
my $a;
if (&isLeapYear($year) && $mon > 2) {
$a = 1;
} else {
$a = 0;
}
($day + ($mon - 1) * 31
- (0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7)[$mon - 1]
+ $a);
}
# int daysOfMonth(int mon, int year) -- days of the month.
#
# mon, year:
# ex. 2, 1992
# return:
# 29 ... 1992 is leap year.
sub daysOfMonth
{
my ($mon, $year) = @_;
(31, 28 + &isLeapYear($year), 31, 30, 31, 30,
31, 31, 30, 31, 30, 31)[$mon - 1];
}
# int dayOfWeek(int mon, int day, int year) -- day of week as a number.
#
# mon, day, year:
# ex. 7, 1, 1994
# return:
# 5 (Fri) ... 7, 1, 1994 is Friday (0:Sun, 1:Mon, ... , 6:Sat)
#
sub dayOfWeek
{
my ($mon, $day, $year) = @_;
(&dayOfYear($mon, $day, $year) + ($year -1) * 365
+ int(($year - 1) / 4)
- int(($year - 1) / 100)
+ int(($year - 1) / 400)) % 7;
}
### Copyright Notice:
## Copyright (C) 1999 Yoshinari Nomura.
## All rights reserved.
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
##
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## 3. Neither the name of the team nor the names of its contributors
## may be used to endorse or promote products derived from this software
## without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY Yoshinari Nomura AND CONTRIBUTORS ``AS IS''
## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
## FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
## Yoshinari Nomura OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
## INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
## SERVICES# LOSS OF USE, DATA, OR PROFITS# OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
## OF THE POSSIBILITY OF SUCH DAMAGE.
### mscan2 ends here