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

来源:互联网 发布:淘宝首页全屏去店招 编辑:程序博客网 时间:2024/04/30 12:55

 实现求某天的前一天操作


其实每次跟闰年打交道时,都会想起小学数学全区统考时的考题,
问: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:
就写到这儿吧,写这篇文章主要是推荐第三种方案的实现思路,特新奇,在做别的开发时,也许会用到,所以供大家参考。第二种代码是同事提供的,好像是网上找来的,如果侵犯到谁的著作权,请及时通知我,我删除即可。不过,因为没有用于赢利行为,应该会允许的吧,知识共享嘛。呵呵~
总之,谢谢第二种方案的提供者。

原创粉丝点击