【问题标题】:rtoday() ESQL function for Perl?Perl 的 rtoday() ESQL 函数?
【发布时间】:2016-03-23 19:29:59
【问题描述】:

我目前正在将 Informix ESQL/C 程序重写为 Perl。我遇到的问题之一是试图在 Perl 中获得与 rtoday() 完全相同的值。

查看 IBM 的文档后: http://www.ibm.com/support/knowledgecenter/SSGU8G_11.50.0/com.ibm.esqlc.doc/sii-xbrstod-41016.htm%23sii-xbrstod-41016

"today
A pointer to an int4 value that receives the internal DATE.
Usage
The rtoday() function obtains the system date on the client computer, not 
the server computer."

在命令行上执行 echo $DATE 时,我得到:

username@myServer:/u/aDir/ $ echo $DATE
2457470 for March 23, 2016

但是当我通过昨天在我的 Unix 机器上的日志获取值时,我有:

42447 for March 22,2016

(日志来自我的 ESQL 程序)

问题是我需要使用rtoday() 值,以便将该值导出到平面文件(连同其他数据)中,以便其他程序进行处理。

我只需要知道如何在 Perl 中或通过系统命令行获取此值,以便我可以使用它。

【问题讨论】:

  • 我假设您的 Perl 脚本将在客户端上运行并使用 DBI 或类似的东西连接到远程数据库?
  • @ThisSuitIsBlackNot Perl 脚本将在与数据库相同的服务器上运行。 ESQL 程序也是如此
  • 我认为您需要弄清楚的是他们计算internal date 的方式(那里的示例脚本中名为i_date 的变量。
  • @ThisSuitIsBlackNot 我想我找到了它:Informix ESQL/C 支持 SQL DATE 数据类型和主变量的 Informix ESQL/C 日期数据类型。日期数据类型存储内部 DATE 值。它实现为一个 4 字节整数,其值为自 1899 年 12 月 31 日以来的天数。1899 年 12 月 31 日之前的日期是负数,而 1899 年 12 月 31 日之后的日期是正数。有关 SQL DATE 数据类型的完整描述,请参阅 IBM® Informix® Guide to SQL: Reference。
  • 我很困惑为什么你从我这里得到的值如此不同——我在 2016 年 3 月 23 日得到了 42451,但你的值却有 3 个不同 (42448)。您检查过系统时钟和/或 TZ 值吗?

标签: perl date unix informix


【解决方案1】:

手册页来自 Informix ESQL/C。

您需要知道 Informix 中的日期是从第 0 天开始的天数,即 1899-12-31 - 所以第 1 天是 1900-01-01。

#include <stdio.h>
#include "sqlhdr.h"

int main(void)
{
    int4 date;
    rtoday(&date);
    printf("%ld\n", date);
    return 0;
}

当我在 2016 年 3 月 23 日运行这个 (Informix ESQL/C) 程序时,我得到响应 42451。当我测试 SQL 时:

$ sqlcmd -d stores "select date('2016-03-22') - date('1899-12-31')
>                     from informix.systables where tabid = 1"

输出为 42450,这与 ESQL/C 程序一致(尽管 sqlcmd——来自IIUG,不是微软最近发明的同名——也是一个 ESQL/C 程序)。与问题中显示的值不一致(2016-03-22 为 42447);我不知道为什么会有差异。仅作记录,我在 RHEL 5 Linux for x86_64 上使用 ESQL/C 3.70.FC4(和 Informix 11.70.FC4),在 Mac OS X 10.11.4 上使用 ESQL/C 4.10.FC5(和 Informix 12.10.FC5) .我不希望在任何其他平台上与 ESQL/C 3.50 (Informix 11.50) 有任何区别。

日期 1970-01-01 的序号为 25568,使用相同的方案。因此,您可以使用以下方法将 time 的值转换为正确的值:

$ perl -le 'print time, " ", int(time/(24*60*60))+25568'               
1458764790 42451
$ perl -le 'sub informix_date_from_unix_time { return int($_[0]/86400) + 25568; }
>           print time, " ", informix_date_from_unix_time(time)'
1458765443 42451
$

这是核心答案,在 UTC 时区是准确的;您需要仔细考虑日期边界和时区以及您想要的答案。

【讨论】:

    【解决方案2】:

    您是否尝试过使用echo $DATE 作为命令调用system

       @args = ("command", "arg1", "arg2");
       system(@args) == 0
            or die "system @args failed: $?"
    

    或者您可以使用%ENV hash 从 Perl 访问环境变量:

    $ perl -e 'print $ENV{"DATE"}'
    

    【讨论】:

    • 不给我与 rtoday() 相同的结果
    • 我在 2016 年 3 月 23 日的 rtoday() 中得到 42448
    【解决方案3】:

    从您所指的 IBM 网站上发布的代码(粘贴在下面)看来,rtoday() 返回今天日期的内部表示,并且该表示需要格式化为 rdatestr功能。这可能意味着,这种表示完全依赖于实现。

    #include <stdio.h>
    
    main()
    {
       mint errnum;
       char today_date[20];
       int4 i_date;
    
       printf("RTODAY Sample ESQL Program running.\n\n");
    
        /* Get todays date in the internal format */
       rtoday(&i_date);
    
        /* Convert date from internal format into a mm/dd/yyyy string */
       if ((errnum = rdatestr(i_date, today_date)) == 0)
          printf("\n\tTodays date is %s.\n", today_date);
       else
          printf("\n\tError %d in converting date to mm/dd/yyyy\n", errnum);
    
       printf("\nRTODAY Sample Program over.\n\n");
    }
    

    【讨论】:

    • 它是一种依赖于实现的日期编码,但它独立于机器(并且独立于操作系统)并且可以在使用 Informix 的系统之间移植。 Informix ESQL/C 库中支持 DATE 操作,例如 rtoday()rdatestr() 以及其他一些函数。
    【解决方案4】:

    所以经过一些工作和我正在寻找的价值的详细定义,我想出了这个:

    #!/opt/standard_perl/perl5881/bin/perl
    use Date::Calc qw(:all);
    
    
    my $date = "03/19/2016";
    
    print getSQLDate($date);
    
    sub getSQLDate
    {
    
    my $value = shift;
    my @date = split('/', $value);
    
    my $alphaDay = 31;
    my $alphaMonth = 12;
    my $alphaYear = 1899;
    
    my @alphaDate = ($alphaYear, $alphaMonth,$alphaDay);
    my @currentDate = ($date[2], $date[0], $date[1]);
    return Delta_Days(@alphaDate, @currentDate);
    
    }
    

    我的输出是:

    42447
    

    我是根据我发现的关于我的 SQL 日期的定义这样做的:

    Informix ESQL/C 通过 Informix ESQL/C 支持 SQL DATE 数据类型 主机变量的日期数据类型。日期数据类型存储内部 DATE 价值观。它被实现为一个 4 字节的整数,其值为天数 自 1899 年 12 月 31 日以来。1899 年 12 月 31 日之前的日期为负数, 而 1899 年 12 月 31 日之后的日期是正数。对于一个完整的 SQL DATE 数据类型的描述,请参阅 IBM® Informix® Guide to SQL: 参考。

    【讨论】:

    • 啊哈;你有 2016-03-19 生产 42447;这与我的预期一致。
    猜你喜欢
    • 2015-12-05
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 2017-02-28
    相关资源
    最近更新 更多