實現求某天的前一天操作(C++,shell)

 實現求某天的前一天操作


其實每次跟閏年打交道時,都會想起小學數學全區統考時的考題,
問: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:
就寫到這兒吧,寫這篇文章主要是推薦第三種方案的實現思路,特新奇,在做別的開發時,也許會用到,所以供大家參考。第二種代碼是同事提供的,好像是網上找來的,如果侵犯到誰的著作權,請及時通知我,我刪除即可。不過,因爲沒有用於贏利行爲,應該會允許的吧,知識共享嘛。呵呵~
總之,謝謝第二種方案的提供者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章