阅读csv文件并与今天的日期进行比较

时间:2014-12-05 15:51:01

标签: csv tcl eggdrop

我想阅读holiday.csv文件,并将该文件中的日期与今天的日期进行比较,以确定今天是否为假日。

这是我到目前为止所拥有的......

文件= holiday.csv

日期,假日名称,美国假日即:

Dec 25,Christmas,US Holiday  
Jan 1,New Year,US Holiday  
Jan 19,Martin Luther King,US Holiday

伪代码:

package require csv
proc mktopen {min hour day month weekday} {
global stockchan
    if {get date's from holiday.csv and compare to today's date if TRUE then} {
        putserv "privmsg #channel :\0030,4 09:30ET\0030,12 ((( US MARKET CLOSED -   US HOLIDAY ))) \017"
    } else {
        putserv "privmsg #channel :\0030,4 09:30ET\0030,12 ((( US MARKET OPEN ))) \017"
    }

}

2 个答案:

答案 0 :(得分:1)

我会首先从csv文件中获取所有日期,然后将其与当前日期进行比较。

但是,我没有那么多地使用csv包,并且我没有发现一个命令只能从csv表中获取一列,所以我将提供一个不使用csv包的解决方案:

# Open the file for reading
set holiday_file [open "holiday.csv" r]

# Get all the holidays in a list called $holidays
set holidays [list]
while {[gets $holiday_file line] != -1} {
    lappend holidays [lindex [split $line ,] 0]
}

# Get today's date in the required format
set today [clock format [clock scan now] -format "%b %d"]
lset today 1 [format %d [lindex $today 1]]

# Compare with today's date
if {[lsearch -exact $holidays $today] > -1} {
    putserv "privmsg #channel :\0030,4 09:30ET\0030,12 ((( US MARKET CLOSED -   US HOLIDAY ))) \017"
} else {
    putserv "privmsg #channel :\0030,4 09:30ET\0030,12 ((( US MARKET OPEN ))) \017"
}

答案 1 :(得分:0)

Csv是一种棘手的格式,使用不完整的解析器来读取csv数据通常是不可取的。当然,这从未阻止任何人这样做。

如果有人想通过这本书来做,咒语就是这样。

package require csv
package require struct::matrix

创建一个矩阵数据结构,它将保存csv文件中的数据并使我们能够使用它:

::struct::matrix m

m现在是当前命名空间中的命令(您可以在名称中添加命名空间以在另一个命名空间中创建它)。完成矩阵后,您应该致电m destroy

您也可以让模块为您的矩阵命令命名并通过变量使用它:

set m [::struct::matrix]

现在您有了一个矩阵,您可以将csv文件的内容加载到其中:

set ch [open holiday.csv]
::csv::read2matrix $ch m , auto
chan close $ch

(您可以使用m serialize进行检查(为了便于阅读,我添加了一些换行符):)

3 3 {
    {{Dec 25} Christmas {US Holiday  }}
    {{Jan 1} {New Year} {US Holiday  }}
    {{Jan 19} {Martin Luther King} {US Holiday}}
}

搜索指定日期:

proc findDate date {
    m search column 0 $date
}

要在第三列中搜索给定字符串:

proc findStr str {
    m search -glob column 2 $str*
}

(由于列中的某些值具有垃圾尾随空格,因此我们需要按string match规则(-glob)进行搜索,而不是默认的完全匹配。)

这两个命令都会返回搜索已显示的单元格列表。单元格由列/行对值指定,例如, {0 2}表示第一列第三行的匹配。

如果我们只是想知道文件中是否出现给定日期,则该谓词将执行:

proc hasDate date {
    expr {[llength [findDate $date]] > 0}
}

但是如果我们想确定日期所在的行确实包含美国假日,我们也需要检查第三列。有很多方法可以做到这一点。对于其中之一,我首先需要一个辅助函数来将单元格描述符列表转换为行号列表:

proc getRowNums cells {
    lmap cell $cells {lindex $cell 1}
}

现在我可以检查日期和字符串,如下所示:

proc hasDateAndString {date str} {
    set r1 [getRowNums [findDate $date]]
    set r2 [getRowNums [findStr $str]]
    # do any rows overlap?
    foreach r $r1 {
        if {$r in $r2} {
            return true
        }
    }
    return false
}

这可以通过检查两个行列表是否共享任何值来实现。如果他们不这样做,则该日期不会指定美国假期。

另一种方法是按行遍历矩阵并检查每行的相关项目:

proc hasDateAndString {date str} {
    for {set row 0} {$row < [m rows]} {incr row} {
        lassign [m get row $row] dateVal - strVal
        if {$date eq $dateVal && [string match $str* $strVal]} {
            return true
        }
    }
    return false
}

对于我看到的每一行,我使用m get row $rowlassign这些值将值列表提取到我可以检查的变量中。

注意:struct::matrix并不适合使用。人们说它很慢,而且更糟糕的是它在隐藏低级细节方面并不是很擅长。在某些情况下, less 使用普通的Tcl I / O读取csv文件,使用::csv::split从每行获取字段并在使用{{ 1}}再次将它们转换为csv字符串。

文档:chancsvexprforforeachiflassign,{{3 }},llengthlmapopenpackageprocreturnsetstring

struct::matrix