您的位置:首页 > 运维架构 > Shell

实现求某天的前一天操作(C++,shell)

2012-02-09 11:31 316 查看
实现求某天的前一天操作

其实每次跟闰年打交道时,都会想起小学数学全区统考时的考题,

问:2100年是否是闰年?当时我们班几乎是全军覆没,老师特别生气地跟我们说,

书上小字部分都有说明,能被4和100整除,但不能被400整除的也不是闰年。我没讲到,你们就不知道看书吗?

当时的情景仍然历历在目,我觉得这辈子,什么是闰年估计我应该不会再出错了。呵呵~

言归正传,看看这题目应该如何来实现呢。可能最传统最常用的方式就是判断是否是闰年?以及大小月来计算吧。呵呵~

最常用的方式就是直接用程序来实现,也比较简单易理解。

程序如下:

void GetYesterday(char* today, string &yesterday)

{

int day = atoi(today + 6);

char buff[9];

strcpy(buff, today+4);

buff[2] = '\0';

int month = atoi(buff);

strcpy(buff, today);

buff[4]='\0';

int year = atoi(buff);

//当为1号时,

if(day == 1)

{

if(month == 1)

{

year -= 1;

month = 12;

day = 31;

}

else

{

month -= 1;

switch(month)

{

case 1:

case 3:

case 5:

case 7:

case 8:

case 10:

case 12:

day = 31;

break;

case 2:

if(isLeap(year))

{

day = 29;

}

else

{

day = 28;

}

break;

default:

day = 30;

break;

}

}

}

else

{

day -= 1;

}

char chbuff[9];

sprintf(chbuff, "%4d%.2d%.2d", year, month, day);

yesterday = chbuff;

}

第二种方式是在 通过shell来实现,思路也比较容易理解。(朋友提供的方案)

看一下代码,应该能看明白,先是取出年,月,日,对日做减一操作。

再判断是否为0,为0时,需要对月做减一操作,当月为0时,直接对年做减一操作,

取12月31号日期即可。若月不为0,则需要判定是否是闰年,以及大小月的关系。

#!/bin/sh

# ydate: A Bourne shell script that

# prints yestarday's date

# Output Form: Month Day Year

# From Focus on Unix: http://unix.about.com

# Set the current month day and year.

month=`date +%m`

day=`date +%d`

year=`date +%Y`

# Add 0 to month. This is a

# trick to make month an unpadded integer.

month=`expr $month + 0`

# Subtract one from the current day.

day=`expr $day - 1`

# If the day is 0 then determine the last

# day of the previous month.

if [ $day -eq 0 ]; then

# Find the preivous month.

month=`expr $month - 1`

# If the month is 0 then it is Dec 31 of

# the previous year.

if [ $month -eq 0 ]; then

month=12

day=31

year=`expr $year - 1`

# If the month is not zero we need to find

# the last day of the month.

else

case $month in

1|3|5|7|8|10|12) day=31;

4|6|9|11) day=30;

2)

if [ `expr $year % 4` -eq 0 ]; then

if [ `expr $year % 400` -eq 0 ]; then

day=29

elif [ `expr $year % 100` -eq 0 ]; then

day=28

else

day=29

fi

else

day=28

fi

;;

esac

fi

fi

# Print the month day and year.

echo $month $day $year

exit 0

第三种实现方式:

上面两种实现方式可以说是比较普遍,易于理解的。下面再一看一种,说实话,代码我第一次看时,需要没理解。后来和同事一点点分析,才明白。当时真的是感叹编写这段代码的人的思路够奇,够新。

不信,看看?呵呵~

function getYesterday

{

today=$1

if [[ -z $today ]]; then

today=`date +%Y%m%d`

fi

y_year=`echo $today | cut -c1-4`

m_month=`echo $today | cut -c5-6`

m_day=`echo $today | cut -c7-8`

date_cal=`cal $m_month $y_year`

if [ $m_day -le 1 ]; then

m_month2=`expr $m_month-1|bc`

if [ $m_month2 -le 0 ];then

m_month=12

y_year=`expr $y_year-1|bc`

date_cal=`cal $m_month $y_year`

else

date_cal=`cal $m_month2 $y_year`

m_month=$m_month2

fi

m_day=`echo $date_cal|awk '{print $NF}'`

else

m_day=`expr $m_day-1|bc`

fi

len=`expr length $m_month`

if [ $len -le 1 ];then

m_month=0$m_month

fi

if [ "$m_day" -le "9" ];then

m_day=0$m_day

fi

echo $y_year$m_month$m_day

}

看明白了吗?

咱们来分析一下代码,开始很好理解,同样地是拆分出年,月,日来。对日做判定,当日为1时,月做减1操作,判断此时当月份为0时,对年做减1操作,取12月31号即可。当此时月不为1时,

date_cal=`cal $m_month2 $y_year`取得上个月的日期表,再通过m_day=`echo $date_cal|awk '{print $NF}'`,其中echo $date_cal实现了将日期横向打印的操作,而awk '{print $NF}'实现了取每行最后一列的操作,故取出上个月的最后一天,而无需去判定是否是闰年?是大小月的问题。

很妙吧。呵呵~

这里需要注意一个问题,当单纯地执行cal $m_month2 $y_year时,是按正常周一至周日纵向来打印日期,而 用echo实现了横向打印操作。

{print $NF}实现了取每行的最后一列操作,注意和取最后一列的区别。

听同事说,可以用 boost来实现,有空我再试试看。呵呵~

PS:

就写到这儿吧,写这篇文章主要是推荐第三种方案的实现思路,特新奇,在做别的开发时,也许会用到,所以供大家参考。第二种代码是同事提供的,好像是网上找来的,如果侵犯到谁的著作权,请及时通知我,我删除即可。不过,因为没有用于赢利行为,应该会允许的吧,知识共享嘛。呵呵~

总之,谢谢第二种方案的提供者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: