曾经沧海难为水,除却巫山不是云。|

Joey-Wang

园龄:4年3个月粉丝:17关注:0

3.4 日期处理

3.4 日期处理

http://codeup.cn/contest.php?cid=100000578

A 日期差值

image-20200703001346743

题目解析

  1. 为方便计算,设置第二个日期大于第一个日期,即time2>time1。

  2. 为方便直接取出每个月的天数,定义一个二维数组int month[13][2] 用于存放每个月的天数(第二维为0时表示平年,为1时表示闰年)。

  3. ⚠️若两个日期连续,则规定二者之间天数为2天。则若两个日期相同,则答案为1。

方法一

令time1不断加1天,直到time1=time2,统计累加的天数。

具体处理时:若加1天后,天数d等于当前月份m拥有天数+1,则m++,d=1;若月份m>12,则y++,m=1。

方法二

为节约时间,可先把time1的年份y1不断加1,直到与time2的年份y2相差1,期间:

  • 若当前y1是闰年且d1<=2(证明闰年的2月还没过完,要算入累加天数)累加366天。

    Eg:time1=20200101; time2=20220101——输出732

  • 若当前(y1+1)是闰年且d1>2(证明第二年的闰年2月要算)累加366天。

    Eg:time1=20190303; time2=20210303——输出732

  • 上述两种之外的情况累加365天。

    Eg:time1=20200303; time2=20220303——输出731(y1是闰年,但d1>2)

然后进行上述不断天数+1操作。

代码1

#include <cstdio>

bool isLeap(int year) {
    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}

int main() {
    int time1, time2;
    //第二维第一个表示平年的月份,第二个表示闰年的月份
    int month[13][2] = {{0,  0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
    int y1, y2, m1, m2, d1, d2;
    while (scanf("%d%d", &time1, &time2) != EOF) {
        int temp;
        int ans = 1;
        if (time1 > time2) {
            temp = time1;
            time1 = time2;
            time2 = temp;
        }
        y1 = time1 / 10000, m1 = (time1 % 10000) / 100, d1 = time1 % 100;
        y2 = time2 / 10000, m2 = (time2 % 10000) / 100, d2 = time2 % 100;
        while (y1 != y2 || m1 != m2 || d1 != d2) {
            d1++;
            ans++;
            if (d1 > month[m1][isLeap(y1)]) {
                m1++;
                d1 = 1;
            }
            if (m1 > 12) {
                y1++;
                m1 = 1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

代码2

#include <cstdio>

bool isLeap(int year) {
    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
int main() {
    int time1, time2;
    //第二维第一个表示平年的月份,第二个表示闰年的月份
    int month[13][2] = {{0,  0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
    int y1, y2, m1, m2, d1, d2;
    while (scanf("%d%d", &time1, &time2) != EOF) {
        int temp;
        int ans = 1;
        if (time1 > time2) {
            temp = time1;
            time1 = time2;
            time2 = temp;
        }
        y1 = time1 / 10000, m1 = (time1 % 10000) / 100, d1 = time1 % 100;
        y2 = time2 / 10000, m2 = (time2 % 10000) / 100, d2 = time2 % 100;
        while (y2 - y1 > 1) {
            if (isLeap(y1) && d1<=2) ans += 366;
            else if (isLeap(y1+1) && d1>2) ans+=366;
            else ans += 365;
            y1++;
        }
        while (y1 != y2 || m1 != m2 || d1 != d2) {
            d1++;
            ans++;
            if (d1 > month[m1][isLeap(y1)]) {
                m1++;
                d1 = 1;
            }
            if (m1 > 12) {
                y1++;
                m1 = 1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

B Day of Week

image-20200703164945413

题目解析

要求一日期所表示的星期。

采用基姆拉尔森公式w = (d + 1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 【w=0~6,w=0表示周日至周六】

公式要求:

  • 将1、2月作为前一年的13、14月

(PS:若采用公式w = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 ,则w=0~6表示周一至周日)

公式原理参考:https://blog.csdn.net/qq_33114231/article/details/52352668

代码

#include <cstdio>
#include <cstring>

int getWeek(int y, int m, int d) {
    if (m == 1 || m == 2) {
        m += 12;
        y--;
    }
    return (d + 1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
}

int main() {
    char week[7][20] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
    char month[13][20] = {"", "January", "February", "March", "April", "May", "June", "July", "August", "September",
                          "October", "November", "December"};
    int y, m, d, w;
    char mm[20];
    while (scanf("%d %s %d", &d, mm, &y) != EOF) {
        for (int i = 1; i <= 12; i++) {
            if (strcmp(month[i], mm) == 0) {
                m = i;
                break;
            }
        }
        printf("%s\n", week[getWeek(y, m, d)]);
    }
    return 0;
}

扩展

若求某年第几天的星期:

w = (d + y - 1 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400) % 7 【w=0~6,w=0表示周日至周六】

  1. 初步推导

    • 用 y, d, w 分别表示 年 该年第几天 星期 (w=0-6 代表星期日-星期六 )

    • 我们从 公元0年1月1日星期日 开始

    • 只考虑最开始的 7 天,即 d = 1---7 变换到 w = 0---6
      很直观的得到: w = d-1

      则该年第 d 天:w = (d - 1) % 7 --------- 公式(1)

    • 按年扩展:

      • 我们不考虑闰年,假设每一年都是 365 天。由于365是7的52倍多1天,所以每一年的第一天和最后一天星期是相同的。
        也就是说下一年的第一天与上一年的第一天星期滞后一天。这是个重要的结论,每过一年,公式(1)会有一天的误差,由于我们是从0年开始的,所以只须要简单的加上年就可以修正扩展年引起的误差,得到公式如下:
        w = (d-1 + y) % 7
      • 将闰年考虑进去
        每个闰年会多出一天,会使后面的年份产生一天的误差。如我们要计算2005年1月1日星期几,就要考虑前面的已经过的2004年中有多少个闰年,将这个误差加上就可以正确的计算了。
        根据闰年的定义(能被4整但不能被100整除或能被400整),得到计算闰年的个数的算式:y/4 - y/100 + y/400(计算从公元0年开始过去的闰年数,公元0年不算闰年)。
        由于我们要计算的是当前要计算的年之前的闰年数,所以要将年减1,得到了如下的公式:
        w = [ d - 1+ y + (y - 1) / 4 - (y - 1) / 100+(y - 1) / 400] % 7 -----公式(2)

C 打印日期

image-20200703180045283

代码

#include <cstdio>

bool isLeap(int y) {
    return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}

int main() {
    int month[13][2] = {{0,  0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
    int y, m, d, n;
    while (scanf("%d %d", &y, &n) != EOF) {
        m = 1, d = 0;
        if (n < 31) d = n;
        else {
            int temp = isLeap(y);
            while (n > month[m][temp]) {
                n -= month[m][temp];
                m++;
            }
            d = n;
        }
        printf("%04d-%02d-%02d\n", y, m, d);
    }
    return 0;
}

D 日期类

image-20200703180343424

代码

#include <cstdio>

bool isLeap(int y) {
    return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}

int main() {
    int M, y, m, d;
    int month[13][2] = {{0,  0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
    while (scanf("%d", &M) != EOF) {
        while (M--) {
            scanf("%d %d %d", &y, &m, &d);
            d++;
            if (d > month[m][isLeap(y)]) {
                m++;
                d = 1;
            }
            if (m > 12) {
                y++;
                m = 1;
            }
            printf("%04d-%02d-%02d\n", y, m, d);
        }
    }
    return 0;
}

E 日期累加

image-20200703180533674

代码

#include <cstdio>

bool isLeap(int y) {
    return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}

int main() {
    int M, y, m, d, n;
    int month[13][2] = {{0,  0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
    while (scanf("%d", &M) != EOF) {
        while (M--) {
            scanf("%d %d %d %d", &y, &m, &d, &n);
            if (n > 366 && isLeap(y) && d <= 2) {
                y++;
                n -= 366;
            } else if (n > 365 && isLeap(y) && d > 2) {
                y++;
                n -= 365;
            } else if (n > 366 && isLeap(y + 1) && d > 2) {
                y++;
                n -= 366;
            } else if (n > 365) {
                y++;
                n -= 365;
            }
            while (n--) {
                d++;
                if (d > month[m][isLeap(y)]) {
                    m++;
                    d = 1;
                }
                if (m > 12) {
                    y++;
                    m = 1;
                }
            }
            printf("%04d-%02d-%02d\n", y, m, d);
        }
    }
    return 0;
}

本文作者:Joey-Wang

本文链接:https://www.cnblogs.com/joey-wang/p/14541162.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Joey-Wang  阅读(93)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开