`
zhengliweb
  • 浏览: 812 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

C写了一个简单的1900-2100日历

阅读更多

练手用的,没写注释,很简单的小东西。

本来打算用C标准库的时间,没能很好理解其中一些细节,放弃了,自己写个玩下。

这应该算是一个demo,用来计算生日还是可以的,计算两个日期差几天。

好吧,上代码,没经过系统测试,喜欢复制去就可以了。

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// calendar struct 
struct cal_m
{
    int c_year;    /* years since 1900 */
    int c_mon;
    int c_day;
    
};

// total days from 1900-01-01
typedef int cal_l;

const char *week_str[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};

//both [0] and [12] mean December.  [1]-January, [2]-February, ...
const int month_days[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// return 0-6 --> week_str[0-6]
int cal_week ( int y, int m, int d )
{
    if ( m == 1 || m == 2 )
    {
        m += 12;
        y--;
    }
    return ( d + 2 * m + 3 * ( m + 1 ) / 5 + y + y / 4 - y / 100 + y / 400 ) % 7;
}

// is leap year
int isleap ( int y )
{
    return ( y % 400 == 0 ) || ( ( y % 4 == 0 ) && ( y % 100 != 0 ) ) ;
}

// cal_m to cal_l
cal_l cal_m2l ( struct cal_m *cm )
{
    int i = 0;
    cal_l days = 0;
    for ( i = 1901; i <= cm->c_year; ++i )
    {
        days += 365;
        if ( i != cm->c_year )
        {
            days += isleap ( i );
        }
    }
    if ( cm->c_mon > 2 && isleap ( cm->c_year ) )
    {
        days += 1;
    }
    for ( i = 1; i < cm->c_mon; i++ )
    {
        days += month_days[i];
    }
    days += ( cm->c_day - 1 );
    return days;
}

//cal_l to cal_m
struct cal_m cal_l2m ( cal_l cl )
{
    int i;
    struct cal_m cm = {0};
    int month_days[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    for ( i = 1900; cl > ( 365 + isleap ( i ) ); i++ )
    {
        cl -= 365;
        cl -= isleap ( i );
    }
    cm.c_year = i;
    
    month_days[2] += isleap ( cm.c_year );
    for ( i = 1; i <= 12 && cl >= month_days[i]; i++ )
    {
        cl -= month_days[i];
    }
    month_days[2] -= isleap ( cm.c_year );
    cm.c_mon = i;
    
    cm.c_day = cl + 1;
    
    return cm;
}

// demo: print  how many days between birthday and today
void cal_diff ( struct cal_m cm0, struct cal_m cm1 )
{
    int years = 0;
    int months = 0;
    int days = 0;
    cal_l cl0 = 0;
    cal_l cl1 = 0;
    years = cm1.c_year - cm0.c_year;
    if ( cm1.c_mon < cm0.c_mon )
    {
        years--;
    }
    else if ( ( cm1.c_mon == cm0.c_mon ) && ( cm1.c_day < cm0.c_day ) )
    {
        years--;
    }
    months = ( cm1.c_mon - cm0.c_mon + 12 ) % 12;
    if (  ( cm1.c_day < cm0.c_day ) )
    {
        months = ( months + 11 ) % 12;
    }
    days = ( cm1.c_day - cm0.c_day + month_days[ ( cm1.c_mon + 11 ) % 12] ) 
    % month_days[ ( cm1.c_mon + 11 ) % 12];
    cl0 = cal_m2l ( &cm0 );
    cl1 = cal_m2l ( &cm1 );
    fprintf ( stdout, "------------------------------------------------\n" );
    fprintf ( stdout, "%.4i-%.2i-%.2i, %s\n", cm0.c_year, cm0.c_mon, cm0.c_day, 
             week_str[cal_week ( cm0.c_year, cm0.c_mon, cm0.c_day )] );
    fprintf ( stdout, "%.4i-%.2i-%.2i, %s\n", cm1.c_year, cm1.c_mon, cm1.c_day, 
             week_str[cal_week ( cm1.c_year, cm1.c_mon, cm1.c_day )] );
    fprintf ( stdout, "\n" );
    fprintf ( stdout, "%d days\n", cl1 - cl0 );
    fprintf ( stdout, "%d weeks, %d days\n",  ( cl1 - cl0 ) / 7, ( cl1 - cl0 ) % 7 );
    fprintf ( stdout, "%d months, %d days\n", months + years * 12, days );
    fprintf ( stdout, "%d years, %d months, %d days\n", years, months, days );
    fprintf ( stdout, "%d years, %d months, %d weeks, %d days\n", years, months, 
             days / 7, days % 7 );
    fprintf ( stdout, "------------------------------------------------\n" );
    return;
}

// range [1900.01.01 - 2100.12.31]
int check ( int year, int month, int day )
{
    int month_days[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    month_days[2] = ( 28 + isleap ( year ) );
    if ( year < 1900 || year > 2100 )
    {
        return 0;
    }
    else if ( month < 0 || month > 12 )
    {
        return 0;
    }
    else if ( day < 0 || day > 31 )
    {
        return 0;
    }
    else if ( day > month_days[month] )
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

void usage ( void )
{
    fprintf ( stdout, "Usage: <year>,<month>,<day>\n" );
    return;
}

//c main
int main ( int argc, char *argv[] )
{
    struct cal_m cm0 = {0};
    struct cal_m cm1 = {0};
    int year0, month0, day0;
    int year1, month1, day1;
    time_t t_now;
    struct tm *tm_now;
    char buff[BUFSIZ] = {0};
    t_now = time ( NULL );
    tm_now = localtime ( &t_now );
    year1 = tm_now->tm_year + 1900;
    month1 = tm_now->tm_mon + 1;
    day1 = tm_now->tm_mday;
    cm1.c_year = year1;
    cm1.c_mon = month1;
    cm1.c_day = day1;
    usage();
    while ( 1 )
    {
        fgets ( buff, BUFSIZ, stdin );
        year0 = month0 = day0 = 0;
        sscanf ( buff, "%d,%d,%d", &year0, &month0, &day0 );
        if ( !check ( year0, month0, day0 ) )
        {
            fprintf ( stderr, "INPUT ERROR! EXIT(-1)\n" );
            exit ( -1 );
        }
        cm0.c_year = year0;
        cm0.c_mon = month0;
        cm0.c_day = day0;
        cal_diff ( cm0, cm1 );
    }
    return 0;
}

 

 下面是运行截图,

运行截图

 

http://zhengliweb.wordpress.com

 

http://zhengliweb.iteye.com

 

 

分享到:
评论

相关推荐

    C语言课程设计-万年历源码.zip

    在本项目中,我们关注的是一个基于C语言的课程设计——万年历程序。这个程序旨在帮助用户查询任何年份的公历日期,提供了一种简单直观的方式来查看和理解日期之间的关系。C语言是一种基础且强大的编程语言,常用于...

    万年历C代码!.rar

    在本资源中,我们主要探讨的是一个用C语言编写的万年历程序。万年历是一种可以显示公历年、月、日以及星期等信息的工具,对于编程爱好者来说,实现一个万年历是一项有趣的挑战,同时也能够提升对日期计算和编程逻辑...

    1602液晶+温度+ds1302+万年历

    DS1302不仅可以提供小时、分钟、秒的信息,还能存储年、月、日、星期等日期信息,从而实现从1900年到2100年的万年历功能。 - 通过单片机程序,可以实时更新1602液晶屏上的日期和时间显示。 5. **编程语言**: - ...

    电子万年历制作 数码管显示

    电子万年历是一种常见的时间显示设备,它能准确地显示当前日期和时间,并且具有足够的存储能力,可以涵盖从公元1900年至公元2100年甚至更远的日期范围。在本项目中,我们将探讨如何使用数码管来显示这样的万年历。 ...

    wnl.rar_万年历1602

    本项目中,我们将深入探讨如何使用51单片机驱动1602液晶显示器来实现一个功能完备的万年历。万年历是一种能够显示当前日期和时间的设备,对于学习单片机编程和硬件接口设计来说,是一个非常实用且有趣的项目。 1. *...

    基于单片机的电子万年历-大学毕业论文设计.doc

    电子万年历是一种能够显示当前日期、时间,并且考虑到闰年规则,可以准确计算直至2100年的日期设备。它在日常生活、工作和学习中发挥着重要作用,尤其在银行、车站、码头、办公室、家庭等场所广泛使用。随着科技的...

    一个日历的类(AS2.0),包含农历,节日,节气,生肖,天干地支等的转换方法

    1. **`lunarInfo`**: 一个数组,存储了1900年到2100年之间农历月份的信息。 2. **`solarMonth`**: 存储了每个月份的标准天数(不考虑闰月)。 3. **`Gan`**: 天干数组,用于表示天干信息。 4. **`Zhi`**: 地支数组,...

    ds1302中文资料

    - DS=01: 选择一个二极管。 - DS=10: 选择两个二极管。 - DS=00或11: 即使TCS=1010,充电功能也被禁止。 #### 5. 接口软件及功能应用 - **写保护寄存器操作**: - 通过命令字节8E/8F控制写保护寄存器的状态。 - ...

    DS1302.pdfDS1302.pdf

    DS1302 内部集成了一个高精度实时时钟/日历模块和 31 字节的静态 RAM。通过串行接口与外部微处理器进行通信,能够提供秒、分、时、日、月、年等时间信息,并能自动调整每月天数(包括闰年的处理)。此外,该芯片还...

    DS1302中文资料

    DS1302集成了一款实时时钟/日历和31字节静态RAM,通过简单的串行接口与微处理器进行通信。实时时钟/日历可以提供秒、分、小时、日、日期、月和年等信息,并自动调整每月天数,包括闰年的调整。该芯片在工作电压范围...

    万年历时钟的程序设计及proteus下仿真

    万年历时钟是一种能够显示当前日期和时间的装置,它能涵盖从公元1900年到公元2100年的日期范围,甚至更远。在电子领域,万年历时钟通常通过单片机(Microcontroller)进行编程实现,其中C语言是最常见的编程语言之一...

    DS1302详细资料

    芯片内部有一个实时时钟模块和一个 31 字节的静态 RAM。实时时钟模块负责时间的计数和维护,而静态 RAM 则用于存储用户数据或其他信息。芯片还支持两种不同的工作电压(VCC1 和 VCC2),其中 VCC1 为主电源,而 VCC2...

    [单片机毕设]基于AT89S52单片机和DS1302的电子万年历设计资料.zip

    本文将深入探讨一个基于AT89S52单片机和DS1302实时时钟芯片的电子万年历设计项目,这通常是一个常见的毕业设计课题,旨在培养学生的实践能力和理论知识的综合运用。 AT89S52是一款高性能、低功耗的8位微控制器,...

    DS1302涓流充电时钟保持芯片的原理与应用

    1. 实时时钟功能强大,可以精确计算从1900年到2100年的秒、分、时、日、日期、星期、月、年,同时具备闰年自动调整功能。 2. 31字节的RAM存储空间,可以用于存储额外的数据或设置。 3. 使用串行I/O接口,只需3个引脚...

    ds1302 使用说明书

    DS1302 内置了一个实时时钟 / 日历模块和 31 字节的静态 RAM。它通过简单的串行接口与微处理器进行通信,使得接口设计变得非常简单。实时时钟 / 日历模块提供了秒、分、小时、日期、月份、星期几以及年份的信息。每...

    基于51单片机的时钟

    【基于51单片机的时钟】是一个利用51系列单片机实现的数字时钟项目,它具有丰富的功能,如显示时分、月日、年份,并且集成了万年历功能,具备整点报时以及定时自动或手动关闭显示器的特性,以实现空闲模式下的低功耗...

    DS1302手册

    它具有多种功能,包括维护实时时钟(RTC)计数,计数秒、分、时、月中的日、月、星期和年份,还具备闰年补偿功能,此功能一直到2100年都有效。DS1302还包含一个31字节的电池备份非易失性(NV)RAM,用于数据存储。它...

    时钟芯片ds1302

    - **实时时钟精度**:具备计算2100年之前的秒、分、时、日、日期、星期、月、年的能力,并能够自动调整闰年。 - **RAM存储容量**:31字节静态RAM。 - **工作电压范围**:宽范围工作电压,2.0V至5.5V。 - **工作电流*...

Global site tag (gtag.js) - Google Analytics