#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/