【问题标题】:"strptime" in SWI-PrologSWI-Prolog 中的“strptime”
【发布时间】:2015-12-17 02:20:32
【问题描述】:

如何将 atom '2015-12-15T05 PST' 转换为时间戳或日期时间?

我试过parse_time/3

?- parse_time('2015-12-15T05 PST', '%Y-%m-%dT%H %Z', Stamp)
false.

format_time/3

?- format_time('2015-12-15T05 PST', '%Y-%m-%dT%H %Z', date(Y,M,D,H,M,S,O,TZ,DST)).
ERROR: format_time/3: Arguments are not sufficiently instantiated

【问题讨论】:

    标签: prolog swi-prolog


    【解决方案1】:

    根据文档,format_time/3 的模式并不能真正帮助你,因为它期待所有的东西都被传入:

    format_time(+Out, +Format, +StampOrDateTime)

    这意味着您提供每个参数。你想看到带有 - 前缀的东西,这意味着它正在交回一些东西,这似乎意味着parse_time/3,但是文档说:

    Text 支持的格式如下表所示。

    然后它会准确列出两个选项,rfc_1123iso_8601,这两个选项都不符合您的格式。这里似乎没有提供格式代码的方法,我觉得这很令人费解,因为这里有底层的 Unix 库肯定可以做到这一点。

    不过,这个问题可以用大家最喜欢的工具来解决:定句语法!这是我的解决方案:

    :- use_module(library(dcg/basics)).
    
    myformat(date(Y,M,D,H,_,_,_,TZ,_)) -->
        integer(Y), "-", integer(M), "-", integer(D),
        "T", integer(H), " ", timezone(TZ).
    
    timezone('UTC') --> "UTC".
    timezone('UTC') --> "GMT".
    timezone(-18000) --> "PST".
    timezone(Secs) -->
        [Sign], digit(H0), digit(H1), digit(M0), digit(M1),
        {
         (Sign = 0'+ ; Sign = 0'-),
         number_codes(Hour, [H0,H1]),
         number_codes(Minutes, [M0, M1]),
         (Sign = 0'+
         -> Secs is Hour * 3600 + Minutes * 60
         ;  Secs is -(Hour * 3600 + Minutes * 60))
        }.
    
    my_time_parse(Atom, Date) :-
        atom_codes(Atom, Codes),
        phrase(myformat(Date), Codes).
    

    我相信学过的人会找到改进此代码的方法,但它对我来说是用您的示例数据解决的问题。不幸的是,您将需要枚举时区或找到更好的数据源(也许解析系统时区定义?)但如果您先验地知道您只需要处理 PST,您可以尝试一下。这是一个例子:

    ?- my_time_parse('2015-12-15T05 PST', Date).
    Date = date(2015, 12, 15, 5, _G3204, _G3205, _G3206, -18000, _G3208) ;
    false.
    

    希望这会有所帮助!

    【讨论】:

    • 非常酷的解决方案。我从你的回答中学到了很多。我只是希望有一个更方便的解决方案:)。
    • 我也是……我不完全确定为什么情况如此糟糕,但是一旦你有时间,你可以使用julian,这真的很有趣!
    【解决方案2】:

    这个问题迟到了:所需的格式接近到 iso_8601,它将采用"2015-12-15T05-08" 的格式。要将时区" PST" 替换为"-08",我们可以使用append。代码:

    :- set_prolog_flag(double_quotes, chars).
    
    timezone(" PST", "-08").
    timezone(" PDT", "-07").
    %% etc
    
    convert_time(Date, Stamp) :- 
        timezone(Zone, Delta),
        append(Front, Zone, Date),
        append(Front, Delta, Date2),
        string_chars(Date3, Date2),
        parse_time(Date3, iso_8601, Stamp).
    
    test :-
        convert_time("2015-12-15T05 PST", Stamp),
        writeln('Stamp'=Stamp),
        fail.
    

    有输出

    ?- test.
    Stamp=1450184400.0
    false.
    

    【讨论】:

      猜你喜欢
      • 2016-01-16
      • 2011-04-26
      • 2016-09-05
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多