strptime windows实现

 strptime 函数windows平台上实现 收藏

 
strptime  函数windows平台上实现
     Linux 平台下Strptime是格式化一个串到时间格式,听好用的,可惜在windows没有实现,翻阅了C库,直接移植过来,做了简单的测试,还行!但缺少一个函数strcasecmp的实现,将“AM”,“PM”(上下午)
的格式注释掉了,想必大家格式串用上下午的还不多吧。献给大家,希望能用的上。
#include  <ctype.h>
#include  <string.h>
#include  <time.h>
 
 
/*
 * We do not implement alternate representations. However, we always
 * check whether a given modifier is allowed for a certain conversion.
 */
#define  ALT_E          0x01
#define  ALT_O          0x02
//#define LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
#define  LEGAL_ALT(x)       { ; }
#define  TM_YEAR_BASE   (1970)
 
static    int conv_num(const char **, int *, int, int);
static  int strncasecmp(char *s1, char *s2, size_t n);
 
static  const char *day[7] = {
     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
     "Friday", "Saturday"
};
static  const char *abday[7] = {
     "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
};
static  const char *mon[12] = {
     "January", "February", "March", "April", "May", "June", "July",
     "August", "September", "October", "November", "December"
};
static  const char *abmon[12] = {
     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static  const char *am_pm[2] = {
     "AM", "PM"
};
 
 
char  *
strptime(const char *buf, const char *fmt, struct tm *tm)
{
     char c;
     const char *bp;
     size_t len = 0;
     int alt_format, i, split_year = 0;
 
     bp = buf;
 
     while ((c = *fmt) != '/0') {
         /* Clear `alternate' modifier prior to new conversion. */
         alt_format = 0;
 
         /* Eat up white-space. */
         if (isspace(c)) {
              while (isspace(*bp))
                   bp++;
 
              fmt++;
              continue;
         }
                  
         if ((c = *fmt++) != '%')
              goto literal;
 
 
again:        switch (c = *fmt++) {
         case '%': /* "%%" is converted to "%". */
literal :
              if (c != *bp++)
                   return (0);
              break;
 
         /*
          * "Alternative" modifiers. Just set the appropriate flag
          * and start over again.
          */
         case 'E': /* "%E?" alternative conversion modifier. */
              LEGAL_ALT(0);
              alt_format |= ALT_E;
              goto again;
 
         case 'O': /* "%O?" alternative conversion modifier. */
              LEGAL_ALT(0);
              alt_format |= ALT_O;
              goto again;
             
         /*
          * "Complex" conversion rules, implemented through recursion.
          */
         case 'c': /* Date and time, using the locale's format. */
              LEGAL_ALT(ALT_E);
              if (!(bp = strptime(bp, "%x %X", tm)))
                   return (0);
              break;
 
         case 'D': /* The date as "%m/%d/%y". */
              LEGAL_ALT(0);
              if (!(bp = strptime(bp, "%m/%d/%y", tm)))
                   return (0);
              break;
 
         case 'R': /* The time as "%H:%M". */
              LEGAL_ALT(0);
              if (!(bp = strptime(bp, "%H:%M", tm)))
                   return (0);
              break;
 
         case 'r': /* The time in 12-hour clock representation. */
              LEGAL_ALT(0);
              if (!(bp = strptime(bp, "%I:%M:%S %p", tm)))
                   return (0);
              break;
 
         case 'T': /* The time as "%H:%M:%S". */
              LEGAL_ALT(0);
              if (!(bp = strptime(bp, "%H:%M:%S", tm)))
                   return (0);
              break;
 
         case 'X': /* The time, using the locale's format. */
              LEGAL_ALT(ALT_E);
              if (!(bp = strptime(bp, "%H:%M:%S", tm)))
                   return (0);
              break;
 
         case 'x': /* The date, using the locale's format. */
              LEGAL_ALT(ALT_E);
              if (!(bp = strptime(bp, "%m/%d/%y", tm)))
                   return (0);
              break;
 
         /*
          * "Elementary" conversion rules.
          */
         case 'A': /* The day of week, using the locale's form. */
         case 'a':
              LEGAL_ALT(0);
              for (i = 0; i < 7; i++) {
                   /* Full name. */
                   len = strlen(day[i]);
                   if (strncasecmp((char *)(day[i]), (char *)bp, len) == 0)
                       break;
 
                   /* Abbreviated name. */
                   len = strlen(abday[i]);
                   if (strncasecmp((char *)(abday[i]), (char *)bp, len) == 0)
                       break;
              }
 
              /* Nothing matched. */
              if (i == 7)
                   return (0);
 
              tm->tm_wday = i;
              bp += len;
              break;
 
         case 'B': /* The month, using the locale's form. */
         case 'b':
         case 'h':
              LEGAL_ALT(0);
              for (i = 0; i < 12; i++) {
                   /* Full name. */
                   len = strlen(mon[i]);
                   if (strncasecmp((char *)(mon[i]), (char *)bp, len) == 0)
                       break;
 
                   /* Abbreviated name. */
                   len = strlen(abmon[i]);
                   if (strncasecmp((char *)(abmon[i]),(char *) bp, len) == 0)
                       break;
              }
 
              /* Nothing matched. */
              if (i == 12)
                   return (0);
 
              tm->tm_mon = i;
              bp += len;
              break;
 
         case 'C': /* The century number. */
              LEGAL_ALT(ALT_E);
              if (!(conv_num(&bp, &i, 0, 99)))
                   return (0);
 
              if (split_year) {
                   tm->tm_year = (tm->tm_year % 100) + (i * 100);
              } else {
                   tm->tm_year = i * 100;
                   split_year = 1;
              }
              break;
 
         case 'd': /* The day of month. */
         case 'e':
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
                   return (0);
              break;
 
         case 'k': /* The hour (24-hour clock representation). */
              LEGAL_ALT(0);
              /* FALLTHROUGH */
         case 'H':
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
                   return (0);
              break;
 
         case 'l': /* The hour (12-hour clock representation). */
              LEGAL_ALT(0);
              /* FALLTHROUGH */
         case 'I':
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
                   return (0);
              if (tm->tm_hour == 12)
                   tm->tm_hour = 0;
              break;
 
         case 'j': /* The day of year. */
              LEGAL_ALT(0);
              if (!(conv_num(&bp, &i, 1, 366)))
                   return (0);
              tm->tm_yday = i - 1;
              break;
 
          case 'M': /* The minute. */
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
                   return (0);
              break;
 
         case 'm': /* The month. */
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &i, 1, 12)))
                   return (0);
              tm->tm_mon = i - 1;
              break;
 
//       case 'p': /* The locale's equivalent of AM/PM. */
//            LEGAL_ALT(0);
//            /* AM? */
//            if (strcasecmp(am_pm[0], bp) == 0) {
//                 if (tm->tm_hour > 11)
//                     return (0);
//
//                 bp += strlen(am_pm[0]);
//                 break;
//            }
//            /* PM? */
//            else if (strcasecmp(am_pm[1], bp) == 0) {
//                 if (tm->tm_hour > 11)
//                     return (0);
//
//                 tm->tm_hour += 12;
//                 bp += strlen(am_pm[1]);
//                 break;
//            }
//
//            /* Nothing matched. */
//            return (0);
 
         case 'S': /* The seconds. */
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
                   return (0);
              break;
 
         case 'U': /* The week of year, beginning on sunday. */
         case 'W': /* The week of year, beginning on monday. */
              LEGAL_ALT(ALT_O);
              /*
               * XXX This is bogus, as we can not assume any valid
               * information present in the tm structure at this
               * point to calculate a real value, so just check the
               * range for now.
               */
               if (!(conv_num(&bp, &i, 0, 53)))
                   return (0);
               break;
 
         case 'w': /* The day of week, beginning on sunday. */
              LEGAL_ALT(ALT_O);
              if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
                   return (0);
              break;
 
         case 'Y': /* The year. */
              LEGAL_ALT(ALT_E);
              if (!(conv_num(&bp, &i, 0, 9999)))
                   return (0);
 
              tm->tm_year = i - TM_YEAR_BASE;
              break;
 
         case 'y': /* The year within 100 years of the epoch. */
              LEGAL_ALT(ALT_E | ALT_O);
              if (!(conv_num(&bp, &i, 0, 99)))
                   return (0);
 
              if (split_year) {
                   tm->tm_year = ((tm->tm_year / 100) * 100) + i;
                   break;
              }
              split_year = 1;
              if (i <= 68)
                   tm->tm_year = i + 2000 - TM_YEAR_BASE;
              else
                   tm->tm_year = i + 1900 - TM_YEAR_BASE;
              break;
 
         /*
          * Miscellaneous conversions.
          */
         case 'n': /* Any kind of white-space. */
         case 't':
              LEGAL_ALT(0);
              while (isspace(*bp))
                   bp++;
              break;
 
 
         default: /* Unknown/unsupported conversion. */
              return (0);
         }
 
 
     }
 
     /* LINTED functional specification */
     return ((char *)bp);
}
 
 
static  int
conv_num(const char **buf, int *dest, int llim, int ulim)
{
     int result = 0;
 
     /* The limit also determines the number of valid digits. */
     int rulim = ulim;
 
     if (**buf < '0' || **buf > '9')
         return (0);
 
     do {
         result *= 10;
         result += *(*buf)++ - '0';
         rulim /= 10;
     } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
 
     if (result < llim || result > ulim)
         return (0);
 
     *dest = result;
     return (1);
}
 
int  strncasecmp(char *s1, char *s2, size_t n)
{
 if (n == 0)
    return 0;
 
 while (n-- != 0 && tolower(*s1) == tolower(*s2))
    {
      if (n == 0 || *s1 == '/0' || *s2 == '/0')
     break;
      s1++;
      s2++;
    }
 
 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
}
 
 
// 测试
#include  <conio.h>
void  main()
{
     struct tm newtime;
     memset(&newtime,0x00,sizeof(struct tm));
 
     strptime("Tue, 27 Nov 2007 05:35:53","%a, %d %b %Y %H:%M:%S",&newtime);
//       strptime("03/10/2004 15:54:19","%d/%m/%Y %H:%M:%S",&newtime);
 
     getch();
 
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值