免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: quakelee
打印 上一主题 下一主题

还是日期计算!! [复制链接]

论坛徽章:
0
1 [报告]
发表于 2003-05-19 20:31 |显示全部楼层

还是日期计算!!

原帖由 "quakelee" 发表:
...
我现在要求不高,就要能算出前一天的日期就行
但是因为是用在跨月份的那一天,所以不是简单的+1 -1就行了
一定是准确的日期
我希望最好别用脚本...


是啊,要求不是很高,但是却很刁,SunOS 的 date 命令行不提供此功能,又不让用脚本,那怎么办?

好吧,不用脚本就不用脚本。


方法一、自己编译一下


  1. #include <stdio.h>
  2. #include <time.h>

  3. int main()
  4. {
  5.        time_t     today;
  6.        struct tm  yesterday;
  7.        time(&today);
  8.        today = today - 86400;
  9.        yesterday = *localtime(&today);
  10.        yesterday.tm_mon ++;
  11.        printf("%02d %02d\n", yesterday.tm_mon, yesterday.tm_mday);
  12.       return(0);
  13. }

复制代码



方法二、可以设定一下 $TZ ,让时区的 offset 为 -86400 ,不过我现在没法试,而且不建议用这个方法,因为对其它程序可能会有意想不到的后果。

论坛徽章:
0
2 [报告]
发表于 2003-05-19 20:45 |显示全部楼层

还是日期计算!!

原帖由 "quakelee" 发表:
靠,算了用脚本就用脚本吧,红袖jj教教我用脚本怎么弄
因为是用在跨月的时候,就是每个月一号
所以前一天的日期一定要算的准,算错了我可死了
况且我是要符合%Y%m%d的格式


我现在马上要走了,没时间了。

你可以找一下旧帖,以前 nkliyong 写过一套关于日期的函数,也包括你要的“前一天”问题,你可以拿来用。如果还搞不定的的话,回头我再回复。

88

论坛徽章:
0
3 [报告]
发表于 2003-05-20 00:59 |显示全部楼层

还是日期计算!!

也不知道你弄好了没有?

因为你实际上要求的是上个月的最后一天,比较偷懒而且在Solaris上可行的方法可以这样。

  1. #!/bin/sh
  2. if [ $# -ne 0 ]; then
  3.     DateString=$1
  4.     Year=`echo $DateString | cut -b 1-4`
  5.     Month=`echo $DateString | cut -b 5-6`
  6. else
  7.     Year=`date +%Y`
  8.     Month=`date +%m`
  9. fi

  10. if [ $Month -eq 1 ]; then
  11.     Month=12
  12.     Year=`expr $Year - 1`
  13. else
  14.     Month=`expr $Month - 1`
  15. fi

  16. Cal=`cal $Month $Year`
  17. Yesterday=`echo $Cal | awk '{print $NF}'`
  18. echo "$Year/$Month/$Yesterday"
复制代码


假设上面的脚本叫 a.sh 运行:

./a.sh  [200302]

无参数时,默认为当前月份

论坛徽章:
0
4 [报告]
发表于 2003-05-20 01:11 |显示全部楼层

还是日期计算!!

...

楼上的帖子运行结果为

sleeve@magic:~/test[586]$ a.sh
2003/4/30

sleeve@magic:~/test[587]$ a.sh 190003
1900/2/28

sleeve@magic:~/test[588]$ a.sh 200003
2000/2/29

sleeve@magic:~/test[589]$ a.sh 200403
2004/2/29

sleeve@magic:~/test[590]$ a.sh 210003
2100/2/28

sleeve@magic:~/test[591]$ a.sh 200301
2002/12/31

论坛徽章:
0
5 [报告]
发表于 2003-05-20 01:24 |显示全部楼层

还是日期计算!!

...

如果是要做得正规点,加上闰年的算法,不仅仅可以用在上个月的最后一天这种特殊情况,还可以处理一般情况:

  1. #!/bin/sh

  2. if [ $# -ne 0 ]; then
  3.     DateString=$1
  4.     Year=`echo $DateString | cut -b 1-4`
  5.     Month=`echo $DateString | cut -b 5-6`
  6.     Date=`echo $DateString | cut -b 7-8`
  7. else
  8.     Year=`date +%Y`
  9.     Month=`date +%m`
  10.     Date=`date +%d`
  11. fi

  12. Date=`expr $Date - 1`

  13. if [ $Date -eq 0 ]; then

  14.   Month=`expr $Month - 1`

  15.   if [ $Month -eq 0 ]; then
  16.     Year=`expr $Year - 1`
  17.     Month=12
  18.     Date=31

  19.   else
  20.     case $Month in
  21.       1|3|5|7|8|10|12) Date=31;;
  22.              4|6|9|11) Date=30;;
  23.                     2)
  24.         Date=28
  25.         if [  `expr $Year % 4` -eq 0 -a `expr $Year % 100` -ne 0  -o \
  26.               `expr $Year % 400` -eq 0  ]; then
  27.             Date=29
  28.         fi
  29.       ;;
  30.     esac
  31.   fi
  32. fi
复制代码


运行:(假设为 b.sh ,注意,参数比上面那个脚本多了两位,即日期)

sleeve@magic:~/test[594]$ ./b.sh 19960301
1996/2/29

sleeve@magic:~/test[595]$ ./b.sh 20000301
2000/2/29

sleeve@magic:~/test[596]$ ./b.sh 21000301
2100/2/28

sleeve@magic:~/test[597]$ ./b.sh 20030101
2002/12/31

sleeve@magic:~/test[598]$ ./b.sh
2003/05/18

sleeve@magic:~/test[599]$ ./b.sh 20030511
2003/05/10

论坛徽章:
0
6 [报告]
发表于 2003-05-20 22:43 |显示全部楼层

还是日期计算!!

...

大家过奖了。

To quakelee:

是啊,具体应用过程中是要调试一下的,上面的给出的代码只是个骨架,实际中是应该把可能遇到的情况考虑进去。在这里我给出一些情况,如参数中是否有非法字符、字串太长、太短、含有空格、日期超出范围……等等,但也不可能考虑周全,只能是具体情况具体分析,根据自己的要求来完善。

另外,上面的帖子中漏掉了最后一句打印语句,我今天才看到。居然你也没提起!

修改后代码,供参考:

  1. #!/bin/sh

  2. # since we have to validate the date string more than once
  3. # put the leap year algorithm in subroutine, should be easy
  4. # to be invoked.

  5. leap() {
  6.     case $1 in
  7.             1|3|5|7|8|10|12) Max=31;;
  8.                    4|6|9|11) Max=30;;
  9.                           2) if [ `expr $Year % 4` -eq 0 -a `expr $Year % 100` -ne 0 -o \
  10.                                   `expr $Year % 400` -eq 0 ]; then
  11.                                  Max=29
  12.                              else
  13.                                  Max=28
  14.                              fi
  15.                              ;;
  16.                           *) Max=0
  17.     esac
  18.     echo $Max
  19. }


  20. if [ $# -eq 1 ]; then
  21.     DateString=$1

  22.     # Len=${#DateString}         ## ksh or bash user can use this statement
  23.                                  ## otherwise use the following expression
  24.     Len=`expr "$DateString" : '.*'`

  25.     if [ $Len -gt 8 ]; then
  26.        echo "Date string too long!"
  27.        exit 1
  28.     elif [ $Len -lt 8 ]; then
  29.        echo "Date string too short!"
  30.        exit 1
  31.     fi

  32.     echo $DateString | grep '[^0-9]' > /dev/null 2>&1
  33.     if [ $? -eq 0 ]; then
  34.          echo "Invalid character(s) in date string! "
  35.          exit 1
  36.     fi

  37.     Year=`echo $DateString | cut -b 1-4`
  38.     Month=`echo $DateString | cut -b 5-6`
  39.     Month=`expr $Month - 0`     # remove leading zero
  40.     Date=`echo $DateString | cut -b 7-8`

  41.     DateMax=`leap $Month`

  42.     if [ $Month -gt 12 -o $Month -lt 1 -o $Date -gt $DateMax -o $Date -lt 1 ]; then
  43.          echo "Invalid date string format! either month or date range exceeds. "
  44.          exit 1
  45.     fi
  46.    
  47. else
  48.     Year=`date +%Y`
  49.     Month=`date +%m`
  50.     Date=`date +%d`
  51. fi

  52. Date=`expr $Date - 1`

  53. if [ $Date -eq 0 ]; then

  54.    Month=`expr $Month - 1`

  55.    if [ $Month -eq 0 ]; then
  56.       Year=`expr $Year - 1`
  57.       Month=12
  58.       Date=31

  59.    else
  60.       Date=`leap $Month`
  61.    fi
  62. fi

  63. if [ $# -ge 2 ]; then
  64.     echo "Only ONE argument required!
  65. Parameters will be discarded and use default current date"
  66. fi

  67. printf "%04d/%02d/%02d\n" $Year $Month $Date
复制代码

论坛徽章:
0
7 [报告]
发表于 2003-05-20 22:48 |显示全部楼层

还是日期计算!!

...

运行结果:

sleeve@magic:~/tmp/sh$ b.sh 2003
Date string too short!

sleeve@magic:~/tmp/sh$ b.sh 200312011
Date string too long!

sleeve@magic:~/tmp/sh$ b.sh 200x1201
Invalid character(s) in date string!

sleeve@magic:~/tmp/sh$ b.sh '200 1201'
Invalid character(s) in date string!

sleeve@magic:~/tmp/sh$ b.sh 200 1201
Only ONE argument required!
Parameters will be discarded and use default current date
2003/05/19

sleeve@magic:~/tmp/sh$ b.sh 20030301
2003/02/28

sleeve@magic:~/tmp/sh$ b.sh 20030101
2002/12/31

sleeve@magic:~/tmp/sh$ b.sh
2003/05/19

sleeve@magic:~/tmp/sh$ b.sh 20030707
2003/07/06

sleeve@magic:~/tmp/sh$ b.sh 20040301
2004/02/29

sleeve@magic:~/tmp/sh$ b.sh 20000301
2000/02/29

sleeve@magic:~/tmp/sh$ b.sh 19000301
1900/02/28

sleeve@magic:~/tmp/sh$ b.sh 19000335
Invalid date string format! either month or date range exceeds.

sleeve@magic:~/tmp/sh$ b.sh 20001503
Invalid date string format! either month or date range exceeds.

论坛徽章:
0
8 [报告]
发表于 2003-05-21 17:50 |显示全部楼层

还是日期计算!!

...

原帖由 "nkliyong"] 红袖真认真.[/quote 发表:


蓝酷脚也是呀,

[quote]原帖由 "quakelee" 发表:
这是在freebsd上运行的结果
[: missing ]
3: not found
2003/02/28
值倒是出来了,但是报了两个错误


确实如此,原因是在第11行,因为太长了,分成两行写的,行末原本是个回车

2) if [ `expr $Year % 4` -eq 0 -a `expr $Year % 100` -ne 0 -o \[RETURN]
   `expr $Year % 400` -eq 0 ]; then

但是不知为啥,这个 phpBB 论坛中,从帖中 copy & paste 会在每行的末尾加上补上空格,变成了

2) if [ `expr $Year % 4` -eq 0 -a `expr $Year % 100` -ne 0 -o \[SPACE][RETURN]
   `expr $Year % 400` -eq 0 ]; then

在大多数情况下倒也是无伤大雅的,但是也有时候会出错,比如这里 \ 后面必须跟的是回车,经过转义的回车,表示该语句还没有结束,跟下一行是同一句。

以后,碰到这种情况我会尽量想着提醒一下的。

此外,还有加了空格会出现异常的还有:

... <<EOF
...

EOF

以及

sed '{
  ...
  w file
}
'

等情况。

论坛徽章:
0
9 [报告]
发表于 2003-05-22 00:25 |显示全部楼层

还是日期计算!!

原帖由 "quakelee" 发表:
嘿嘿,我想了个更好的办法,把日志都同步到一台bsd上去处理了
嘿嘿,别生气啊,不过真的谢谢你,shell脚本的编写也学会了不少东西



没问题啊。

对发帖者来说,能最方便地解决问题是最终目的;
对答帖和看帖的来说,交流和互相学习是目的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP