rdate, 时间格式化,在unix系统实现类似linux系统的date命令



#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <time.h>

#include <math.h>


void Func_help()  //帮助函数

{

    printf("NAME:\n");

    printf("    rdate  --display date and time\n");

    printf("SYNOPSIS:\n");

    printf("    rdate [-f] [time format] [-c] [colculation format] \n");

    printf("DESCRIPTION:\n");

    printf("    \n");

    printf("    -c: value is day/month/year,plus +/-,plus a number which is number to colculate\n");

    printf("    \n");

    printf("    -f:\n");

    printf("    \n");

    printf("     %%A    is replaced by national representation of the full weekday name.\n");

    printf("     %%a    is replaced by national representation of the abbreviated weekday name.\n");

    printf("     %%B    is replaced by national representation of the full month name.\n");

    printf("     %%b    is replaced by national representation of the abbreviated month name.\n");

    printf("     %%C    is replaced by (year / 100) as decimal number; single digits are preceded by a zero.\n");

    printf("     %%c    is replaced by national representation of time and date.\n");

    printf("     %%D    is equivalent to ``%%m/%%d/%%y''.\n");

    printf("     %%d    is replaced by the day of the month as a decimal number (01-31).\n");

    printf("     %%E* %%O*\n");

    printf("            POSIX locale extensions.  The sequences %%Ec %%EC %%Ex %%EX %%Ey %%EY %%Od %%Oe %%OH %%OI %%Om %%OM %%OS %%Ou %%OU %%OV %%Ow %%OW %%Oy are supposed to provide alternate\n");

    printf("            representations.\n");

    printf("            Additionally %%OB implemented to represent alternative months names (used standalone, without day mentioned).\n");

    printf("     %%e    is replaced by the day of the month as a decimal number (1-31); single digits are preceded by a blank.\n");

    printf("     %%F    is equivalent to ``%%Y-%%m-%%d''.\n");

    printf("     %%G    is replaced by a year as a decimal number with century.  This year is the one that contains the greater part of the week (Monday as the first day of\n");

    printf("            the week).\n");

    printf("     %%g    is replaced by the same year as in ``%%G'', but as a decimal number without century (00-99).\n");

    printf("     %%H    is replaced by the hour (24-hour clock) as a decimal number (00-23).\n");

    printf("     %%h    the same as %%b.\n");

    printf("     %%I    is replaced by the hour (12-hour clock) as a decimal number (01-12).\n");

    printf("     %%j    is replaced by the day of the year as a decimal number (001-366).\n");

    printf("     %%k    is replaced by the hour (24-hour clock) as a decimal number (0-23); single digits are preceded by a blank.\n");

    printf("     %%l    is replaced by the hour (12-hour clock) as a decimal number (1-12); single digits are preceded by a blank.\n");

    printf("     %%M    is replaced by the minute as a decimal number (00-59).\n");

    printf("     %%m    is replaced by the month as a decimal number (01-12).\n");

    printf("     %%n    is replaced by a newline.\n");

    printf("     %%O*   the same as %%E*.\n");

    printf("     %%p    is replaced by national representation of either ante meridiem (a.m.)  or post meridiem (p.m.)  as appropriate.\n");

    printf("     %%R    is equivalent to ``%%H:%%M''.\n");

    printf("     %%r    is equivalent to ``%%I:%%M:%%S %%p''.\n");

    printf("     %%S    is replaced by the second as a decimal number (00-60).\n");

    printf("     %%s    is replaced by the number of seconds since the Epoch, UTC (see mktime(3)).\n");

    printf("     %%T    is equivalent to ``%%H:%%M:%%S''.\n");

    printf("     %%t    is replaced by a tab.\n");

    printf("     %%U    is replaced by the week number of the year (Sunday as the first day of the week) as a decimal number (00-53).\n");

    printf("     %%u    is replaced by the weekday (Monday as the first day of the week) as a decimal number (1-7).\n");

    printf("     %%V    is replaced by the week number of the year (Monday as the first day of the week) as a decimal number (01-53).  If the week containing January 1 has\n");

    printf("            four or more days in the new year, then it is week 1; otherwise it is the last week of the previous year, and the next week is week 1.\n");

    printf("     %%v    is equivalent to ``%%e-%%b-%%Y''.\n");

    printf("     %%W    is replaced by the week number of the year (Monday as the first day of the week) as a decimal number (00-53).\n");

    printf("     %%w    is replaced by the weekday (Sunday as the first day of the week) as a decimal number (0-6).\n");

    printf("     %%X    is replaced by national representation of the time.\n");

    printf("     %%x    is replaced by national representation of the date.\n");

    printf("     %%Y    is replaced by the year with century as a decimal number.\n");

    printf("     %%y    is replaced by the year without century as a decimal number (00-99).\n");

    printf("     %%Z    is replaced by the time zone name.\n");

    printf("     %%z    is replaced by the time zone offset from UTC; a leading plus sign stands for east of UTC, a minus sign for west of UTC, hours and minutes follow with\n");

    printf("            two digits each and no delimiter between them (common form for RFC 822 date headers).\n");

    printf("     %%+    is replaced by national representation of the date and time (the format is similar to that produced by date(1)).\n");

    printf("     %%-*   GNU libc extension.  Do not do any padding when performing numerical outputs.\n");

    printf("     %%_*   GNU libc extension.  Explicitly specify space for padding.\n");

    printf("     %%0*   GNU libc extension.  Explicitly specify zero for padding.\n");

    printf("     %%%%    is replaced by `%%'.\n");

    printf("    \n");

    printf("EXAMPLE:\n");

    printf("     rdate                                 --2017-10-23 11:04:51 Monday\n");

    printf("     rdate -f \"%%Y-%%m_%%d\"                   --2017-10-23\n");

    printf("     rdate -f \"%%Y-%%m_%%d\" -c \"day-3\"        --2017-10-20\n");

    printf("     rdate -f \"%%Y-%%m_%%d\" -c \"day+3\"        --2017-10-26\n");

    printf("     rdate -f \"%%Y-%%m_%%d\" -c \"month+3\"      --2017-7-23\n");

    printf("     rdate -f \"%%Y-%%m_%%d\" -c \"year+3\"       --2020-7-23\n");

    printf("    \n");

    printf("    \n");

    printf("    \n");

}



int LeapYear(int year)  //判断闰年

{

    int ret = 0;

    

    if ((year%4==0 && year%100!=0) || year%400 == 0) {

        ret = 0;

        

        return ret;

    }

    

    else

    {

        ret =1;

        return ret;

    }

}



struct tm * DayAdd(int dayNUm) //dayNum 单位:天 0代表获取当前时间,整整数代表获取以后的时间,负数代表向前的时间

{

    

    time_t tt,timetmp;

    struct tm * p = NULL;

    

    time(&tt);

    if (tt == -1) {

        

        perror("time");

        

        return p;

    }

    timetmp = 24*60*60 * dayNUm;

    

    if (dayNUm > 0) {

        tt = tt + timetmp;

    }

    else if (dayNUm < 0){

        tt = tt + timetmp;

    }

    

    p = localtime(&tt);

    

    if (p == NULL) {

        

        return

        p;

    }

    

    return p;

}



struct tm * MonthAdd(int monthNum,struct tm * inTm) //inTm为null表示当前时间

{

    time_t tt;

    struct tm * tmTmp;

    int yearCount = 0;

    

    

    if (inTm == NULL) { //判断时候获取当前时间戳

        

        time (&tt);

        tmTmp = localtime(&tt);

    }

    else{

        tmTmp = inTm;

    }

    

    if (monthNum < 0) { //负数代表

        while (1) {

            if (abs(monthNum) >= 12) {

                monthNum+=12;

                yearCount--;

                continue;

            }

            else

            {

                

                break;

            }

        }

        

        if (abs(monthNum) >= (tmTmp->tm_mon+1)) { //判断传入的月数是否大于当前的月份,所以tmTmp->tm_mon+1,因为tm_mon从0开始算

            tmTmp->tm_mon = 12 - (abs(monthNum) - (tmTmp->tm_mon));

            yearCount--;

            //            if (monthNum + (tmTmp->tm_mon+1) <= 0) { //判断是否向前数一年,如果向前一年必须year减一

            //                tmTmp->tm_mon = 12 - (abs(monthNum) - (tmTmp->tm_mon));

            //                yearCount--;

            //            }else

            //            {

            //                tmTmp->tm_mon += monthNum+1;

            //            }

            

            

        }

        else{

            tmTmp->tm_mon+= monthNum;

        }

    }

    else

    {

        

        while (1) { //判断传入的参数是否大于12,把大于12的数换算成年,12个月为一年

            if (monthNum >= 12) {

                monthNum -=12;

                yearCount++;

                continue;

            }

            else

            {

                

                break;

            }

        }

        

        if (monthNum + (tmTmp->tm_mon+1) > 12) { //判断是否需要跨越当前年,如果跨越当前年则年计数器加1

            tmTmp->tm_mon = abs((monthNum + (tmTmp->tm_mon))-12);

            yearCount++;

        }

        else

        {

            tmTmp->tm_mon+= monthNum;

        }

    }

    tmTmp->tm_year+= yearCount;

    

    return tmTmp;

}


struct tm * LastDayOfMonth(int monthNum,struct tm * inTm) //inTm为null表示当前时间

{

    

    int month12[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

    

    time_t tt;

    

    struct tm * tmTmp;

    

    int yearCount = 0;

    

    

    if (inTm == NULL) { //判断时候获取当前时间戳

        time(&tt);

        tmTmp = localtime(&tt);

    }

    else

    {

        tmTmp = inTm;

    }

    

    if (monthNum < 0) { //负数代表

        

        

        while (1) {

            if (abs(monthNum) >= 12) {

                monthNum+=12;

                yearCount--;

                

                continue;

            }

            else

            {

                

                break;

            }

        }

        

        if (abs(monthNum) >= (tmTmp->tm_mon+1)) { //判断传入的月数是否大于当前的月份,所以tmTmp->tm_mon+1,因为tm_mon从0开始算

            

            tmTmp->tm_mon = 12 - (abs(monthNum) - (tmTmp->tm_mon));

            yearCount--;

            

            //            if (monthNum + (tmTmp->tm_mon+1) <= 0) { //判断是否向前数一年,如果向前一年必须year减一

            

            

            //                tmTmp->tm_mon = 12 - (abs(monthNum) - (tmTmp->tm_mon));

            

            

            //                yearCount--;

            

            

            //            }else

            

            

            //            {

            

            

            //                tmTmp->tm_mon += monthNum+1;

            

            

            //            }

            

            

        }

        else

        {

            tmTmp->tm_mon += monthNum;

        }

    }

    else

    {

        

        while (1) { //判断传入的参数是否大于12,把大于12的数换算成年,12个月为一年

            

            if (monthNum >= 12) {

                monthNum -= 12;

                yearCount++;

                

                continue;

            }

            else

            {

                

                break;

            }

        }

        

        if (monthNum + (tmTmp->tm_mon+1) > 12) { //判断是否需要跨越当前年,如果跨越当前年则年计数器加1

            

            tmTmp->tm_mon = abs((monthNum + (tmTmp->tm_mon))-12);

            yearCount++;

        }

        else

        {

            tmTmp->tm_mon += monthNum;

        }

    }

    tmTmp->tm_year += yearCount;

    

    

    if(LeapYear(tmTmp->tm_year+1900) == 1) //不是闰年

    {

        tmTmp->tm_mday = month12[tmTmp->tm_mon];

    }

    else

    {

        

        if (tmTmp->tm_mon == 1) {

            tmTmp->tm_mday = month12[tmTmp->tm_mon]+1;

        }

        else

        {

            tmTmp->tm_mday = month12[tmTmp->tm_mon];

        }

    }

    

    

    return tmTmp;

}


struct tm * YearAdd(int yearNum,struct tm * inTm) //inTm为null表示当前时间

{

    return MonthAdd(yearNum*12, inTm);

}


struct tm * WeekAdd(int weekNum) //inTm为null表示当前时间

{

    return DayAdd(weekNum*7);

}



int ToDigit(char * tmp_str)  //获取需要计算的数字

{

    int ret = 0,num = 0,isMultiSpace = 0,i=0;

    char tmp_array[128];

    for (i=1; i <strlen(tmp_str); i++) {

        if (isdigit(tmp_str[i]) != 0) {

            tmp_array[num]=tmp_str[i];

            num++;

            ret=0;//判断以获取到数字,

            continue;

        }else if (tmp_str[i] == ' ')//判断是否存在空格,允许空格存在,但不允许多个数字参数传入

        {

            if (ret == 0) { //ret为0表示获取到数字

                isMultiSpace++;//判断字符串内是否有多个数字

            }

            ret = 1;//如果获取到空格,则把ret设置成1,表示已经过去过空格

            continue;

        }

        else{//存在除了单个+/-以外的字符

            printf("The value of parameter(-c) include a invalid characcter.");

            exit(4);

        }

    }

    if (isMultiSpace >= 2 && ret==0) { //如果空格超过2并且是刚刚获取过数字,表示数字超过2个。

        printf("Please enter right format number!!\n");

        printf("If you don't kown what values is avalable,please use -h to get help!\n");

        exit(2);

    }

    ret = atoi(tmp_array);

    return ret;

}


struct tm * Colculation(char * ColStr) //计算函数

{

    int ColNum=0;

    struct tm * tmp_tm = NULL;

    char * tmp_char = calloc(128, sizeof(char));

    if (strcasestr(ColStr, "day") != NULL ){//判断是否是在日期(天)需要加减

        if (strchr(ColStr, '-') != NULL && strchr(ColStr, '+') != NULL) {//判断参数内是否同时含有+ -符号

            printf("Please enter right format symbol!!\n");

            printf("If you don't kown what values is avalable,please use -h to get help!\n");

            exit(3);

        }else if (strchr(ColStr, '-') != NULL) {//判断计算是+或-

            strcpy(tmp_char, strchr(ColStr, '-')); //把-号(含-)后面的内容拷贝到指定的字符串

            ColNum=0-ToDigit(tmp_char);//获取需要计算的数字

        }else if (strchr(ColStr, '+') != NULL){

            strcpy(tmp_char, strchr(ColStr, '+'));//把+号(含+)后面的内容拷贝到指定的字符串

            ColNum=0+ToDigit(tmp_char);//获取需要计算的数字

        }

        if (tmp_tm != NULL) {

            free(tmp_tm);

            tmp_tm = NULL;

        }

        tmp_tm = DayAdd(ColNum);//日期(天)计算

    }else if (strcasestr(ColStr, "month") != NULL){//判断是否是在日期(月)需要加减

        if ((strchr(ColStr, '-') != NULL && strchr(ColStr, '+') != NULL) || strchr(strchr(ColStr, '-')+1,'-') != NULL || strchr(strchr(ColStr, '+')+1,'+') != NULL) {

            printf("Please enter right format symbol!!\n");

            printf("If you don't kown what values is avalable,please use -h to get help!\n");

            exit(3);

        }else if (strchr(ColStr, '-') != NULL) {

            strcpy(tmp_char, strchr(ColStr, '-'));

            ColNum=0-ToDigit(tmp_char);

        }else if (strchr(ColStr, '+') != NULL){

            strcpy(tmp_char, strchr(ColStr, '+'));

            ColNum=0+ToDigit(tmp_char);

        }

        if (tmp_tm != NULL) {

            free(tmp_tm);

            tmp_tm = NULL;

        }

        tmp_tm = MonthAdd(ColNum, NULL);

    }else if (strcasestr(ColStr, "year") != NULL){//判断是否是在日期(年)需要加减

        if ((strchr(ColStr, '-') != NULL && strchr(ColStr, '+') != NULL) || strchr(strchr(ColStr, '-')+1,'-') != NULL || strchr(strchr(ColStr, '+')+1,'+') != NULL) {

            printf("Please enter right format symbol!!\n");

            printf("If you don't kown what values is avalable,please use -h to get help!\n");

            exit(3);

        }else if (strchr(ColStr, '-') != NULL) {

            strcpy(tmp_char, strchr(ColStr, '-'));

            ColNum=0-ToDigit(tmp_char);

        }else if (strchr(ColStr, '+') != NULL){

            strcpy(tmp_char, strchr(ColStr, '+'));

            ColNum=0+ToDigit(tmp_char);

        }

        if (tmp_tm != NULL) {

            free(tmp_tm);

            tmp_tm = NULL;

        }

        tmp_tm = YearAdd(ColNum, NULL);

    }else{//如果没有关键字(day,month,year)出现,执行这个出口

        printf("Please enter right value of colculation,-c\n");

        printf("If you don't kown what values is avalable,please use -h to get help!\n");

        exit(1);

    }


    if (tmp_char != NULL) {

        free(tmp_char);

        tmp_char = NULL;

    }

    return tmp_tm;

}



int main(int argc, const char * argv[]) {

    time_t tt;

    struct tm * temp_tm = NULL;

    char * str = calloc(1024, sizeof(char));

    int format_num=0,i=0,ret=0;


    time(&tt);

    

    if(argc < 2){//判断输入的但是,不带参数,执行这里

        temp_tm=localtime(&tt);

        strftime(str, 1024, "%Y-%m-%d %H:%M:%S %A", temp_tm);

        printf("%s\n",str);

    }

    else

    {

        

        for (i=1; i < argc; i++) {//获取参数

            

            if ( strcasecmp(argv[i], "-h") == 0 ) {

                Func_help();

//                break;

                goto End;

            }else if (strcasecmp(argv[i], "-f") == 0){//-f 表示format,输出的时间的格式

                i++;

                if (argv[i] == NULL || strcasecmp(argv[i], "-c") == 0) {

                    printf("The value of -f must be specified!!!\n");

                    exit(4);

                }

                format_num = i;//获取时间格式化的参数的下标位置

                continue;

            }else if (strcasecmp(argv[i], "-c") == 0){//-c 表示colculation,计算的格式,如:day-1

                i++;

                if (argv[i] == NULL  || strcasecmp(argv[i], "-f") == 0) {

                    printf("The value of -c must be specified!!!\n");

                    exit(4);

                }

                temp_tm = Colculation(argv[i]);//执行计算函数,获取最后需要输出的struct tm

                continue;

            }else{

                printf("You must enter right parametr.\n");

                printf("If you don't kown what values is avalable,please use -h to get help!\n");

                ret=1;

                goto End;

            }

        }

        if (temp_tm == NULL) {//如果temp_tm为空,则表示使用当前时间

            temp_tm=localtime(&tt);

        }

        if (format_num == 0) {//如果没有获取时间格式的下标,则使用默认时间输出格式

            strftime(str, 1024, "%Y-%m-%d %H:%M:%S %A", temp_tm);

            printf("%s\n",str);

        }else{//使用获取的时间输出格式的下标,按照时间格式,给str赋值

            strftime(str, 1024, argv[format_num], temp_tm);

            printf("%s\n",str);

        }

        

        

    }


End:

    if (str != NULL) {

        free(str);

        str=NULL;

    }

    if(temp_tm != NULL){

        free(temp_tm);

        temp_tm = NULL;

    }

    return ret;

}



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28572479/viewspace-2146213/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28572479/viewspace-2146213/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值