c日期格式化操作之timestamp

# include "logger.h"
# include < stdio. h>
# include < sys/ types. h>
# include < time. h>
# include < ctype. h>
# include < sys/ time. h>
# include < time. h>
# include < stdlib. h>
# include < string. h>

# define tAGO 257
# define tDAY 258
# define tDAY_UNIT 259
# define tDAYZONE 260
# define tDST 261
# define tHOUR_UNIT 262
# define tID 263
# define tMERIDIAN 264
# define tMINUTE_UNIT 265
# define tMONTH 266
# define tMONTH_UNIT 267
# define tSEC_UNIT 268
# define tSNUMBER 269
# define tUNUMBER 270
# define tYEAR_UNIT 271
# define tZONE 272

# define ISSPACE( c) ( isascii ( c) && isspace ( c))
# define ISALPHA( c) ( isascii ( c) && isalpha ( c))
# define ISUPPER( c) ( isascii ( c) && isupper ( c))
# define ISDIGIT_LOCALE( c) ( isascii ( c) && isdigit ( c))
# define ISDIGIT( c) (( unsigned) ( c) - '0' <= 9) # define EPOCH 1970
# define HOUR( x) (( x) * 60)
# define MAX_BUFF_LEN    128
# define PARSE_DATE_FINAL 62
# define PARSE_DATE_FLAG -32768
# define PARSE_DATE_NTBASE 22
# define PARSE_DATE_TRANSLATE( x) (( unsigned)( x) <= 272 ? parse_date_translate[ x] : 32)
# define PARSE_DATE_LAST 52
# define PARSE_DATE_TERROR 1
# define PARSE_DATE_ERRCODE 256
# define PARSE_DATE_INITDEPTH 200
# define PARSE_DATE_MAXDEPTH 10000
# define TM_YEAR_ORIGIN 1900

# define PARSE_DATE_BACKUP( token, value) \
do \
  if ( parse_date_char == -2 && parse_date_len == 1) \
    { parse_date_char = ( token), parse_date_lval = ( value); \
      parse_date_char1 = PARSE_DATE_TRANSLATE ( parse_date_char); \
      parse_date_vsp--, parse_date_ssp--; \
      goto parse_date_backup; \
    } \
  else \
    { parse_date_error ( "syntax error: cannot back up"); goto parse_date_errlab1; } \
while (0)

typedef struct {
  const char * name;
  int type;
  int value;
} TABLE;

typedef enum {
  MERam, MERpm, MER24
} MERIDIAN;

typedef union {
  int Number;
  MERIDIAN Meridian;
} PARSE_DATE_STYPE;

int parse_date ();
static int parse_date_lex ();
static int parse_date_error ();
static const char * parse_date_Input;
static int parse_date_DayOrdinal;
static int parse_date_DayNumber;
static int parse_date_HaveDate;
static int parse_date_HaveDay;
static int parse_date_HaveRel;
static int parse_date_HaveTime;
static int parse_date_HaveZone;
static int parse_date_Timezone;
static int parse_date_Day;
static int parse_date_Hour;
static int parse_date_Minutes;
static int parse_date_Month;
static int parse_date_Seconds;
static int parse_date_Year;
static MERIDIAN parse_date_Meridian;
static int parse_date_RelDay;
static int parse_date_RelHour;
static int parse_date_RelMinutes;
static int parse_date_RelMonth;
static int parse_date_RelSeconds;
static int parse_date_RelYear;
int parse_date_char;
PARSE_DATE_STYPE parse_date_lval;
int parse_date_nerrs;

static const char parse_date_translate[] = { 0,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 20, 2, 2, 21, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 19, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
  7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
  17, 18
};

static const char * const parse_date_tname[] =
  { "$", "error", "$undefined.", "tAGO", "tDAY",
  "tDAY_UNIT", "tDAYZONE", "tDST", "tHOUR_UNIT", "tID", "tMERIDIAN",
  "tMINUTE_UNIT",
  "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tSNUMBER", "tUNUMBER", "tYEAR_UNIT",
  "tZONE",
  "':'", "','", "'/'", "spec", "item", "time", "zone", "day", "date", "rel",
  "relunit", "number",
  "o_merid", NULL
};

static const short parse_date_r1[] = { 0,
  22, 22, 23, 23, 23, 23, 23, 23, 24, 24,
  24, 24, 24, 25, 25, 25, 26, 26, 26, 27,
  27, 27, 27, 27, 27, 27, 27, 27, 28, 28,
  29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
  29, 29, 29, 29, 29, 29, 29, 29, 30, 31,
  31
};

static const short parse_date_r2[] = { 0,
  0, 2, 1, 1, 1, 1, 1, 1, 2, 4,
  4, 6, 6, 1, 1, 2, 1, 2, 2, 3,
  5, 3, 3, 3, 2, 4, 2, 3, 2, 1,
  2, 2, 1, 2, 2, 1, 2, 2, 1, 2,
  2, 1, 2, 2, 1, 2, 2, 1, 1, 0,
  1
};

static const short parse_date_defact[] = { 1,
  0, 17, 39, 15, 42, 45, 0, 36, 48, 0,
  49, 33, 14, 2, 3, 4, 6, 5, 7, 30,
  8, 18, 25, 38, 41, 44, 35, 47, 32, 19,
  37, 40, 9, 43, 27, 34, 46, 0, 31, 0,
  0, 16, 29, 24, 0, 23, 28, 22, 50, 20,
  26, 51, 11, 0, 10, 0, 50, 21, 13, 12,
  0, 0
};

static const short parse_date_defgoto[] = { 1,
  14, 15, 16, 17, 18, 19, 20, 21, 55
};

static const short parse_date_pact[] = { -32768,
  0, -19, -32768, -32768, -32768, -32768, -13, -32768, -32768, 30,
  15, -32768, 14, -32768, -32768, -32768, -32768, -32768, -32768, 19,
  -32768, -32768, 29, -32768, -32768, -32768, -32768, -32768, -32768, -32768,
  -32768, -32768, -32768, -32768, -6, -32768, -32768, 9, -32768, 17,
  23, -32768, -32768, -32768, 24, -32768, -32768, -32768, 27, 10,
  -32768, -32768, -32768, 32, -32768, 34, -8, -32768, -32768, -32768,
  51, -32768
};

static const short parse_date_pgoto[] = { -32768,
  -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768, -5
};

static const short parse_date_table[] = { 61,
  22, 52, 23, 2, 3, 4, 59, 5, 46, 47,
  6, 7, 8, 9, 10, 11, 12, 13, 30, 31,
  42, 43, 32, 48, 33, 34, 35, 36, 37, 38,
  56, 39, 49, 40, 24, 41, 52, 25, 50, 51,
  26, 53, 27, 28, 44, 54, 29, 57, 45, 58,
  62, 60
};

static const short parse_date_check[] = { 0,
  20, 10, 16, 4, 5, 6, 15, 8, 15, 16,
  11, 12, 13, 14, 15, 16, 17, 18, 4, 5,
  7, 3, 8, 15, 10, 11, 12, 13, 14, 15,
  21, 17, 16, 19, 5, 21, 10, 8, 16, 16,
  11, 15, 13, 14, 16, 19, 17, 16, 20, 16,
  0, 57
};


int
parse_date ()
{
  register int parse_date_state;
  register int parse_date_n;
  register short * parse_date_ssp;
  register PARSE_DATE_STYPE * parse_date_vsp;
  int parse_date_errstatus;
  int parse_date_char1 = 0;

  short parse_date_ssa[ PARSE_DATE_INITDEPTH];
  PARSE_DATE_STYPE parse_date_vsa[ PARSE_DATE_INITDEPTH];

  short * parse_date_ss = parse_date_ssa;
  PARSE_DATE_STYPE * parse_date_vs = parse_date_vsa;

  int parse_date_stacksize = PARSE_DATE_INITDEPTH;
  int parse_date_free_stacks = 0;

  PARSE_DATE_STYPE parse_date_val; /*  the variable used to return         */
  /*  semantic values from the action     */
  /*  routines                            */

  int parse_date_len;

  parse_date_state = 0;
  parse_date_errstatus = 0;
  parse_date_nerrs = 0;
  parse_date_char = -2; /* Cause a token to be read.  */

  /* Initialize stack pointers.
     Waste one element of value and location stack
     so that they stay on the same level as the state stack.
     The wasted elements are never initialized.  */


  parse_date_ssp = parse_date_ss - 1;
  parse_date_vsp = parse_date_vs;

parse_date_constructstate:

  *++ parse_date_ssp = parse_date_state;

  if ( parse_date_ssp >= parse_date_ss + parse_date_stacksize - 1) {
    PARSE_DATE_STYPE * parse_date_vs1 = parse_date_vs;
    short * parse_date_ss1 = parse_date_ss;

    /* Get the current used size of the three stacks, in elements.  */
    int size = parse_date_ssp - parse_date_ss + 1;

    if ( parse_date_stacksize >= PARSE_DATE_MAXDEPTH) {
      parse_date_error ( "parser stack overflow");
      if ( parse_date_free_stacks) {
free ( parse_date_ss);
free ( parse_date_vs);
      }
      return 2;
    }
    parse_date_stacksize *= 2;
    if ( parse_date_stacksize > PARSE_DATE_MAXDEPTH)
      parse_date_stacksize = PARSE_DATE_MAXDEPTH;
    parse_date_ss =
      ( short *) malloc ( parse_date_stacksize * sizeof (* parse_date_ssp));
    //__builtin_memcpy ((char *) parse_date_ss, (char *) parse_date_ss1,
//       size * (unsigned int) sizeof (*parse_date_ssp));
    memcpy (( char *) parse_date_ss, ( char *) parse_date_ss1,
      size * ( unsigned int) sizeof (* parse_date_ssp));
    parse_date_vs =
      ( PARSE_DATE_STYPE *) malloc ( parse_date_stacksize *
   sizeof (* parse_date_vsp));
    //__builtin_memcpy ((char *) parse_date_vs, (char *) parse_date_vs1,
//       size * (unsigned int) sizeof (*parse_date_vsp));
    memcpy (( char *) parse_date_vs, ( char *) parse_date_vs1,
      size * ( unsigned int) sizeof (* parse_date_vsp));

    parse_date_ssp = parse_date_ss + size - 1;
    parse_date_vsp = parse_date_vs + size - 1;


    if ( parse_date_ssp >= parse_date_ss + parse_date_stacksize - 1)
      goto parse_date_abortlab;
  }


  goto parse_date_backup;
parse_date_backup:

  parse_date_n = parse_date_pact[ parse_date_state];
  if ( parse_date_n == PARSE_DATE_FLAG)
    goto parse_date_default;

  if ( parse_date_char == -2) {
    parse_date_char = parse_date_lex ();
  }

  if ( parse_date_char <= 0) { /* This means end of input. */
    parse_date_char1 = 0;
    parse_date_char = 0; /* Don't call parse_date_lex() any more */

  }
  else {
    parse_date_char1 = PARSE_DATE_TRANSLATE ( parse_date_char);

  }

  parse_date_n += parse_date_char1;
  if ( parse_date_n < 0 || parse_date_n > PARSE_DATE_LAST
      || parse_date_check[ parse_date_n] != parse_date_char1)
    goto parse_date_default;

  parse_date_n = parse_date_table[ parse_date_n];

  if ( parse_date_n < 0) {
    if ( parse_date_n == PARSE_DATE_FLAG)
      goto parse_date_errlab;
    parse_date_n = - parse_date_n;
    goto parse_date_reduce;
  }
  else if ( parse_date_n == 0)
    goto parse_date_errlab;

  if ( parse_date_n == PARSE_DATE_FINAL)
    goto parse_date_acceptlab;

  if ( parse_date_char != 0)
    parse_date_char = -2;

  *++ parse_date_vsp = parse_date_lval;

  /* count tokens shifted since error; after three, turn off error status.  */
  if ( parse_date_errstatus)
    parse_date_errstatus--;

  parse_date_state = parse_date_n;
  goto parse_date_constructstate;

/* Do the default action for the current state.  */
parse_date_default:

  parse_date_n = parse_date_defact[ parse_date_state];
  if ( parse_date_n == 0)
    goto parse_date_errlab;

/* Do a reduction.  parse_date_n is the number of a rule to reduce with.  */
parse_date_reduce:
  parse_date_len = parse_date_r2[ parse_date_n];
  if ( parse_date_len > 0)
    parse_date_val = parse_date_vsp[1 - parse_date_len]; /* implement default value of the action */


  switch ( parse_date_n) {

  case 3:
    {
      parse_date_HaveTime++;
      ;
      break;
    }
  case 4:
    {
      parse_date_HaveZone++;
      ;
      break;
    }
  case 5:
    {
      parse_date_HaveDate++;
      ;
      break;
    }
  case 6:
    {
      parse_date_HaveDay++;
      ;
      break;
    }
  case 7:
    {
      parse_date_HaveRel++;
      ;
      break;
    }
  case 9:
    {
      parse_date_Hour = parse_date_vsp[-1]. Number;
      parse_date_Minutes = 0;
      parse_date_Seconds = 0;
      parse_date_Meridian = parse_date_vsp[0]. Meridian;
      ;
      break;
    }
  case 10:
    {
      parse_date_Hour = parse_date_vsp[-3]. Number;
      parse_date_Minutes = parse_date_vsp[-1]. Number;
      parse_date_Seconds = 0;
      parse_date_Meridian = parse_date_vsp[0]. Meridian;
      ;
      break;
    }
  case 11:
    {
      parse_date_Hour = parse_date_vsp[-3]. Number;
      parse_date_Minutes = parse_date_vsp[-1]. Number;
      parse_date_Meridian = MER24;
      parse_date_HaveZone++;
      parse_date_Timezone = ( parse_date_vsp[0]. Number < 0
     ? - parse_date_vsp[0]. Number % 100 +
     (- parse_date_vsp[0]. Number / 100) *
     60 : -( parse_date_vsp[0]. Number % 100 +
    ( parse_date_vsp[0]. Number / 100) * 60));
      ;
      break;
    }
  case 12:
    {
      parse_date_Hour = parse_date_vsp[-5]. Number;
      parse_date_Minutes = parse_date_vsp[-3]. Number;
      parse_date_Seconds = parse_date_vsp[-1]. Number;
      parse_date_Meridian = parse_date_vsp[0]. Meridian;
      ;
      break;
    }
  case 13:
    {
      parse_date_Hour = parse_date_vsp[-5]. Number;
      parse_date_Minutes = parse_date_vsp[-3]. Number;
      parse_date_Seconds = parse_date_vsp[-1]. Number;
      parse_date_Meridian = MER24;
      parse_date_HaveZone++;
      parse_date_Timezone = ( parse_date_vsp[0]. Number < 0
     ? - parse_date_vsp[0]. Number % 100 +
     (- parse_date_vsp[0]. Number / 100) *
     60 : -( parse_date_vsp[0]. Number % 100 +
    ( parse_date_vsp[0]. Number / 100) * 60));
      ;
      break;
    }
  case 14:
    {
      parse_date_Timezone = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 15:
    {
      parse_date_Timezone = parse_date_vsp[0]. Number - 60;
      ;
      break;
    }
  case 16:
    {
      parse_date_Timezone = parse_date_vsp[-1]. Number - 60;
      ;
      break;
    }
  case 17:
    {
      parse_date_DayOrdinal = 1;
      parse_date_DayNumber = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 18:
    {
      parse_date_DayOrdinal = 1;
      parse_date_DayNumber = parse_date_vsp[-1]. Number;
      ;
      break;
    }
  case 19:
    {
      parse_date_DayOrdinal = parse_date_vsp[-1]. Number;
      parse_date_DayNumber = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 20:
    {
      parse_date_Month = parse_date_vsp[-2]. Number;
      parse_date_Day = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 21:
    {
      /* Interpret as PARSE_DATE_PARSE_DATE_/MM/DD if $1 >= 1000, otherwise as MM/DD/PARSE_DATE_.
         The goal in recognizing PARSE_DATE_PARSE_DATE_/MM/DD is solely to support legacy
         machine-generated dates like those in an RCS log listing.  If
         you want portability, use the ISO 8601 format.  */

      if ( parse_date_vsp[-4]. Number >= 1000) {
parse_date_Year = parse_date_vsp[-4]. Number;
parse_date_Month = parse_date_vsp[-2]. Number;
parse_date_Day = parse_date_vsp[0]. Number;
      }
      else {
parse_date_Month = parse_date_vsp[-4]. Number;
parse_date_Day = parse_date_vsp[-2]. Number;
parse_date_Year = parse_date_vsp[0]. Number;
      }
      ;
      break;
    }
  case 22:
    {
      /* ISO 8601 format.  parse_date_date_-mm-dd.  */
      parse_date_Year = parse_date_vsp[-2]. Number;
      parse_date_Month = - parse_date_vsp[-1]. Number;
      parse_date_Day = - parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 23:
    {
      /* e.g. 17-JUN-1992.  */
      parse_date_Day = parse_date_vsp[-2]. Number;
      parse_date_Month = parse_date_vsp[-1]. Number;
      parse_date_Year = - parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 24:
    {
      parse_date_Month = parse_date_vsp[-2]. Number;
      parse_date_Day = parse_date_vsp[-1]. Number;
      parse_date_Year = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 25:
    {
      parse_date_Month = parse_date_vsp[-1]. Number;
      parse_date_Day = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 26:
    {
      parse_date_Month = parse_date_vsp[-3]. Number;
      parse_date_Day = parse_date_vsp[-2]. Number;
      parse_date_Year = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 27:
    {
      parse_date_Month = parse_date_vsp[0]. Number;
      parse_date_Day = parse_date_vsp[-1]. Number;
      ;
      break;
    }
  case 28:
    {
      parse_date_Month = parse_date_vsp[-1]. Number;
      parse_date_Day = parse_date_vsp[-2]. Number;
      parse_date_Year = parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 29:
    {
      parse_date_RelSeconds = - parse_date_RelSeconds;
      parse_date_RelMinutes = - parse_date_RelMinutes;
      parse_date_RelHour = - parse_date_RelHour;
      parse_date_RelDay = - parse_date_RelDay;
      parse_date_RelMonth = - parse_date_RelMonth;
      parse_date_RelYear = - parse_date_RelYear;
      ;
      break;
    }
  case 31:
    {
      parse_date_RelYear +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 32:
    {
      parse_date_RelYear +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 33:
    {
      parse_date_RelYear += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 34:
    {
      parse_date_RelMonth +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 35:
    {
      parse_date_RelMonth +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 36:
    {
      parse_date_RelMonth += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 37:
    {
      parse_date_RelDay +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 38:
    {
      parse_date_RelDay +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 39:
    {
      parse_date_RelDay += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 40:
    {
      parse_date_RelHour +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 41:
    {
      parse_date_RelHour +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 42:
    {
      parse_date_RelHour += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 43:
    {
      parse_date_RelMinutes +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 44:
    {
      parse_date_RelMinutes +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 45:
    {
      parse_date_RelMinutes += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 46:
    {
      parse_date_RelSeconds +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 47:
    {
      parse_date_RelSeconds +=
parse_date_vsp[-1]. Number * parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 48:
    {
      parse_date_RelSeconds += parse_date_vsp[0]. Number;
      ;
      break;
    }
  case 49:
    {
      if ( parse_date_HaveTime && parse_date_HaveDate && ! parse_date_HaveRel)
parse_date_Year = parse_date_vsp[0]. Number;
      else {
if ( parse_date_vsp[0]. Number > 10000) {
  parse_date_HaveDate++;
  parse_date_Day = ( parse_date_vsp[0]. Number) % 100;
  parse_date_Month = ( parse_date_vsp[0]. Number / 100) % 100;
  parse_date_Year = parse_date_vsp[0]. Number / 10000;
}
else {
  parse_date_HaveTime++;
  if ( parse_date_vsp[0]. Number < 100) {
    parse_date_Hour = parse_date_vsp[0]. Number;
    parse_date_Minutes = 0;
  }
  else {
    parse_date_Hour = parse_date_vsp[0]. Number / 100;
    parse_date_Minutes = parse_date_vsp[0]. Number % 100;
  }
  parse_date_Seconds = 0;
  parse_date_Meridian = MER24;
}
      }
      ;
      break;
    }
  case 50:
    {
      parse_date_val. Meridian = MER24;
      ;
      break;
    }
  case 51:
    {
      parse_date_val. Meridian = parse_date_vsp[0]. Meridian;
      ;
      break;
    }
  }
  /* the action file gets copied in in place of this dollarsign */


  parse_date_vsp -= parse_date_len;
  parse_date_ssp -= parse_date_len;
  *++ parse_date_vsp = parse_date_val;

  /* Now "shift" the result of the reduction.
     Determine what state that goes to,
     based on the state we popped back to
     and the rule number reduced by.  */


  parse_date_n = parse_date_r1[ parse_date_n];

  parse_date_state =
    parse_date_pgoto[ parse_date_n - PARSE_DATE_NTBASE] + * parse_date_ssp;
  if ( parse_date_state >= 0 && parse_date_state <= PARSE_DATE_LAST
      && parse_date_check[ parse_date_state] == * parse_date_ssp)
    parse_date_state = parse_date_table[ parse_date_state];
  else
    parse_date_state = parse_date_defgoto[ parse_date_n - PARSE_DATE_NTBASE];

  goto parse_date_constructstate;

parse_date_errlab: /* here on detecting error */

  if (! parse_date_errstatus)
    /* If not already recovering from an error, report this error.  */
  {
    ++ parse_date_nerrs;

    parse_date_error ( "parse error");
  }

  goto parse_date_errlab1;
parse_date_errlab1: /* here on error raised explicitly by an action */

  if ( parse_date_errstatus == 3) {
    /* if just tried and failed to reuse lookahead token after an error, discard it.  */

    /* return failure if at end of input */
    if ( parse_date_char == 0)
      goto parse_date_abortlab;

    parse_date_char = -2;
  }

  /* Else will try to reuse lookahead token
     after shifting the error token.  */


  parse_date_errstatus = 3; /* Each real token shifted decrements this */

  goto parse_date_errhandle;

parse_date_errdefault: /* current state does not do anything special for the error token. */

parse_date_errpop: /* pop the current state because it cannot handle the error token */

  if ( parse_date_ssp == parse_date_ss)
    goto parse_date_abortlab;
  parse_date_vsp--;
  parse_date_state = *-- parse_date_ssp;

parse_date_errhandle:

  parse_date_n = parse_date_pact[ parse_date_state];
  if ( parse_date_n == PARSE_DATE_FLAG)
    goto parse_date_errdefault;

  parse_date_n += PARSE_DATE_TERROR;
  if ( parse_date_n < 0 || parse_date_n > PARSE_DATE_LAST
      || parse_date_check[ parse_date_n] != PARSE_DATE_TERROR)
    goto parse_date_errdefault;

  parse_date_n = parse_date_table[ parse_date_n];
  if ( parse_date_n < 0) {
    if ( parse_date_n == PARSE_DATE_FLAG)
      goto parse_date_errpop;
    parse_date_n = - parse_date_n;
    goto parse_date_reduce;
  }
  else if ( parse_date_n == 0)
    goto parse_date_errpop;

  if ( parse_date_n == PARSE_DATE_FINAL)
    goto parse_date_acceptlab;

  *++ parse_date_vsp = parse_date_lval;

  parse_date_state = parse_date_n;
  goto parse_date_constructstate;

parse_date_acceptlab:
  /* goto parse_date_acceptlab comes here.  */
  if ( parse_date_free_stacks) {
    free ( parse_date_ss);
    free ( parse_date_vs);
  }
  return 0;

parse_date_abortlab:
  /* goto parse_date_abortlab comes here.  */
  if ( parse_date_free_stacks) {
    free ( parse_date_ss);
    free ( parse_date_vs);
  }
  return 1;
}


time_t get_date ( char * p, time_t * now);

/* Month and day table. */
static TABLE const MonthDayTable[] = {
  { "january", tMONTH, 1},
  { "february", tMONTH, 2},
  { "march", tMONTH, 3},
  { "april", tMONTH, 4},
  { "may", tMONTH, 5},
  { "june", tMONTH, 6},
  { "july", tMONTH, 7},
  { "august", tMONTH, 8},
  { "september", tMONTH, 9},
  { "sept", tMONTH, 9},
  { "october", tMONTH, 10},
  { "november", tMONTH, 11},
  { "december", tMONTH, 12},
  { "sunday", tDAY, 0},
  { "monday", tDAY, 1},
  { "tuesday", tDAY, 2},
  { "tues", tDAY, 2},
  { "wednesday", tDAY, 3},
  { "wednes", tDAY, 3},
  { "thursday", tDAY, 4},
  { "thur", tDAY, 4},
  { "thurs", tDAY, 4},
  { "friday", tDAY, 5},
  { "saturday", tDAY, 6},
  { NULL, 0, 0}
};

/* Time units table. */
static TABLE const UnitsTable[] = {
  { "year", tYEAR_UNIT, 1},
  { "month", tMONTH_UNIT, 1},
  { "fortnight", tDAY_UNIT, 14},
  { "week", tDAY_UNIT, 7},
  { "day", tDAY_UNIT, 1},
  { "hour", tHOUR_UNIT, 1},
  { "minute", tMINUTE_UNIT, 1},
  { "min", tMINUTE_UNIT, 1},
  { "second", tSEC_UNIT, 1},
  { "sec", tSEC_UNIT, 1},
  { NULL, 0, 0}
};

/* Assorted relative-time words. */
static TABLE const OtherTable[] = {
  { "tomorrow", tDAY_UNIT, 1},
  { "yesterday", tDAY_UNIT, -1},
  { "today", tDAY_UNIT, 0},
  { "now", tDAY_UNIT, 0},
  { "last", tUNUMBER, -1},
  { "this", tMINUTE_UNIT, 0},
  { "next", tUNUMBER, 1},
  { "first", tUNUMBER, 1},
/*  { "second", tUNUMBER, 2 }, */
  { "third", tUNUMBER, 3},
  { "fourth", tUNUMBER, 4},
  { "fifth", tUNUMBER, 5},
  { "sixth", tUNUMBER, 6},
  { "seventh", tUNUMBER, 7},
  { "eighth", tUNUMBER, 8},
  { "ninth", tUNUMBER, 9},
  { "tenth", tUNUMBER, 10},
  { "eleventh", tUNUMBER, 11},
  { "twelfth", tUNUMBER, 12},
  { "ago", tAGO, 1},
  { NULL, 0, 0}
};

/* The timezone table. */
static TABLE const TimezoneTable[] = {
  { "gmt", tZONE, HOUR (0)}, /* Greenwich Mean */
  { "ut", tZONE, HOUR (0)}, /* Universal (Coordinated) */
  { "utc", tZONE, HOUR (0)},
  { "wet", tZONE, HOUR (0)}, /* Western European */
  { "bst", tDAYZONE, HOUR (0)}, /* British Summer */
  { "wat", tZONE, HOUR (1)}, /* West Africa */
  { "at", tZONE, HOUR (2)}, /* Azores */
  { "ast", tZONE, HOUR (4)}, /* Atlantic Standard */
  { "adt", tDAYZONE, HOUR (4)}, /* Atlantic Daylight */
  { "est", tZONE, HOUR (5)}, /* Eastern Standard */
  { "edt", tDAYZONE, HOUR (5)}, /* Eastern Daylight */
  { "cst", tZONE, HOUR (6)}, /* Central Standard */
  { "cdt", tDAYZONE, HOUR (6)}, /* Central Daylight */
  { "mst", tZONE, HOUR (7)}, /* Mountain Standard */
  { "mdt", tDAYZONE, HOUR (7)}, /* Mountain Daylight */
  { "pst", tZONE, HOUR (8)}, /* Pacific Standard */
  { "pdt", tDAYZONE, HOUR (8)}, /* Pacific Daylight */
  { "yst", tZONE, HOUR (9)}, /* Yukon Standard */
  { "ydt", tDAYZONE, HOUR (9)}, /* Yukon Daylight */
  { "hst", tZONE, HOUR (10)}, /* Hawaii Standard */
  { "hdt", tDAYZONE, HOUR (10)}, /* Hawaii Daylight */
  { "cat", tZONE, HOUR (10)}, /* Central Alaska */
  { "akst", tZONE, HOUR (10)}, /* Alaska Standard */
  { "akdt", tZONE, HOUR (10)}, /* Alaska Daylight */
  { "ahst", tZONE, HOUR (10)}, /* Alaska-Hawaii Standard */
  { "nt", tZONE, HOUR (11)}, /* Nome */
  { "idlw", tZONE, HOUR (12)}, /* International Date Line West */
  { "cet", tZONE, - HOUR (1)}, /* Central European */
  { "met", tZONE, - HOUR (1)}, /* Middle European */
  { "mewt", tZONE, - HOUR (1)}, /* Middle European Winter */
  { "mest", tDAYZONE, - HOUR (1)}, /* Middle European Summer */
  { "mesz", tDAYZONE, - HOUR (1)}, /* Middle European Summer */
  { "swt", tZONE, - HOUR (1)}, /* Swedish Winter */
  { "sst", tDAYZONE, - HOUR (1)}, /* Swedish Summer */
  { "fwt", tZONE, - HOUR (1)}, /* French Winter */
  { "fst", tDAYZONE, - HOUR (1)}, /* French Summer */
  { "eet", tZONE, - HOUR (2)}, /* Eastern Europe, USSR Zone 1 */
  { "bt", tZONE, - HOUR (3)}, /* Baghdad, USSR Zone 2 */
  { "zp4", tZONE, - HOUR (4)}, /* USSR Zone 3 */
  { "zp5", tZONE, - HOUR (5)}, /* USSR Zone 4 */
  { "zp6", tZONE, - HOUR (6)}, /* USSR Zone 5 */
  { "wast", tZONE, - HOUR (7)}, /* West Australian Standard */
  { "wadt", tDAYZONE, - HOUR (7)}, /* West Australian Daylight */
  { "cct", tZONE, - HOUR (8)}, /* China Coast, USSR Zone 7 */
  { "jst", tZONE, - HOUR (9)}, /* Japan Standard, USSR Zone 8 */
  { "east", tZONE, - HOUR (10)}, /* Eastern Australian Standard */
  { "eadt", tDAYZONE, - HOUR (10)}, /* Eastern Australian Daylight */
  { "gst", tZONE, - HOUR (10)}, /* Guam Standard, USSR Zone 9 */
  { "nzt", tZONE, - HOUR (12)}, /* New Zealand */
  { "nzst", tZONE, - HOUR (12)}, /* New Zealand Standard */
  { "nzdt", tDAYZONE, - HOUR (12)}, /* New Zealand Daylight */
  { "idle", tZONE, - HOUR (12)}, /* International Date Line East */
  { NULL, 0, 0}
};

/* Military timezone table. */
static TABLE const MilitaryTable[] = {
  { "a", tZONE, HOUR (1)},
  { "b", tZONE, HOUR (2)},
  { "c", tZONE, HOUR (3)},
  { "d", tZONE, HOUR (4)},
  { "e", tZONE, HOUR (5)},
  { "f", tZONE, HOUR (6)},
  { "g", tZONE, HOUR (7)},
  { "h", tZONE, HOUR (8)},
  { "i", tZONE, HOUR (9)},
  { "k", tZONE, HOUR (10)},
  { "l", tZONE, HOUR (11)},
  { "m", tZONE, HOUR (12)},
  { "n", tZONE, HOUR (-1)},
  { "o", tZONE, HOUR (-2)},
  { "p", tZONE, HOUR (-3)},
  { "q", tZONE, HOUR (-4)},
  { "r", tZONE, HOUR (-5)},
  { "s", tZONE, HOUR (-6)},
  { "t", tZONE, HOUR (-7)},
  { "u", tZONE, HOUR (-8)},
  { "v", tZONE, HOUR (-9)},
  { "w", tZONE, HOUR (-10)},
  { "x", tZONE, HOUR (-11)},
  { "y", tZONE, HOUR (-12)},
  { "z", tZONE, HOUR (0)},
  { NULL, 0, 0}
};



static int parse_date_error ( char * s) {
  s = NULL;
  return 0;
}

static int ToHour ( int Hours, MERIDIAN Meridian) {

  switch ( Meridian) {
      case MER24:
        if ( Hours < 0 || Hours > 23)
          return -1;
        return Hours;
      case MERam:
        if ( Hours < 1 || Hours > 12)
          return -1;
        if ( Hours == 12)
          Hours = 0;
        return Hours;
      case MERpm:
        if ( Hours < 1 || Hours > 12)
          return -1;
        if ( Hours == 12)
          Hours = 0;
        return Hours + 12;
      default:
        abort ();
  }

  return -1;
}

static int ToYear ( int Year) {
  if ( Year < 0)
    Year = - Year;

  /* XPG4 suggests that years 00-68 map to 2000-2068, and
     years 69-99 map to 1969-1999.  */

  if ( Year < 69)
    Year += 2000;
  else if ( Year < 100)
    Year += 1900;

  return Year;
}

static int LookupWord ( char * buff) {
  register char * p;
  register char * q;
  register const TABLE * tp;
  int i;
  int abbrev;

  /* Make it lowercase. */
  for ( p = buff; * p; p++)
    if ( ISUPPER (( unsigned char) * p))
      * p = tolower (* p);

  if ( strcmp ( buff, "am") == 0 || strcmp ( buff, "a.m.") == 0) {
    parse_date_lval. Meridian = MERam;
    return tMERIDIAN;
  }
  if ( strcmp ( buff, "pm") == 0 || strcmp ( buff, "p.m.") == 0) {
    parse_date_lval. Meridian = MERpm;
    return tMERIDIAN;
  }

  /* See if we have an abbreviation for a month. */
  if ( strlen ( buff) == 3)
    abbrev = 1;
  else if ( strlen ( buff) == 4 && buff[3] == '.') {
    abbrev = 1;
    buff[3] = '\0';
  }
  else
    abbrev = 0;

  for ( tp = MonthDayTable; tp-> name; tp++) {
    if ( abbrev) {
      if ( strncmp ( buff, tp-> name, 3) == 0) {
parse_date_lval. Number = tp-> value;
return tp-> type;
      }
    }
    else if ( strcmp ( buff, tp-> name) == 0) {
      parse_date_lval. Number = tp-> value;
      return tp-> type;
    }
  }

  for ( tp = TimezoneTable; tp-> name; tp++)
    if ( strcmp ( buff, tp-> name) == 0) {
      parse_date_lval. Number = tp-> value;
      return tp-> type;
    }

  if ( strcmp ( buff, "dst") == 0)
    return tDST;

  for ( tp = UnitsTable; tp-> name; tp++)
    if ( strcmp ( buff, tp-> name) == 0) {
      parse_date_lval. Number = tp-> value;
      return tp-> type;
    }

  /* Strip off any plural and try the units table again. */
  i = strlen ( buff) - 1;
  if ( buff[ i] == ' s') {
    buff[ i] = '\0';
    for ( tp = UnitsTable; tp-> name; tp++)
      if ( strcmp ( buff, tp-> name) == 0) {
parse_date_lval. Number = tp-> value;
return tp-> type;
      }
    buff[ i] = ' s'; /* Put back for "this" in OtherTable. */
  }

  for ( tp = OtherTable; tp-> name; tp++)
    if ( strcmp ( buff, tp-> name) == 0) {
      parse_date_lval. Number = tp-> value;
      return tp-> type;
    }

  /* Military timezones. */
  if ( buff[1] == '\0' && ISALPHA (( unsigned char) * buff)) {
    for ( tp = MilitaryTable; tp-> name; tp++)
      if ( strcmp ( buff, tp-> name) == 0) {
parse_date_lval. Number = tp-> value;
return tp-> type;
      }
  }

  /* Drop out any periods and try the timezone table again. */
  for ( i = 0, p = q = buff; * q; q++)
    if (* q != '.')
      * p++ = * q;
    else
      i++;
  * p = '\0';
  if ( i)
    for ( tp = TimezoneTable; tp-> name; tp++)
      if ( strcmp ( buff, tp-> name) == 0) {
parse_date_lval. Number = tp-> value;
return tp-> type;
      }

  return tID;
}

static int parse_date_lex () {
  register unsigned char c;
  register char * p;
  char buff[20];
  int Count;
  int sign;

  for (;;) {
    while ( ISSPACE (( unsigned char) * parse_date_Input))
      parse_date_Input++;

    if ( ISDIGIT ( c = * parse_date_Input) || c == '-' || c == '+') {
      if ( c == '-' || c == '+') {
sign = c == '-' ? -1 : 1;
if (! ISDIGIT (*++ parse_date_Input))
  /* skip the '-' sign */
  continue;
      }
      else
sign = 0;
      for ( parse_date_lval. Number = 0; ISDIGIT ( c = * parse_date_Input++);)
parse_date_lval. Number = 10 * parse_date_lval. Number + c - '0';
      parse_date_Input--;
      if ( sign < 0)
parse_date_lval. Number = - parse_date_lval. Number;
      return sign ? tSNUMBER : tUNUMBER;
    }
    if ( ISALPHA ( c)) {
      for ( p = buff; ( c = * parse_date_Input++, ISALPHA ( c)) || c == '.';)
if ( p < & buff[ sizeof buff - 1])
  * p++ = c;
      * p = '\0';
      parse_date_Input--;
      return LookupWord ( buff);
    }
    if ( c != '(')
      return * parse_date_Input++;
    Count = 0;
    do {
      c = * parse_date_Input++;
      if ( c == '\0')
return c;
      if ( c == '(')
Count++;
      else if ( c == ')')
Count--;
    }
    while ( Count > 0);
  }
}


/* Yield A - B, measured in seconds.  */
static long difftm ( struct tm * a, struct tm * b) {
  int ay = a-> tm_year + ( TM_YEAR_ORIGIN - 1);
  int by = b-> tm_year + ( TM_YEAR_ORIGIN - 1);
  long days = (
/* difference in day of year */
a-> tm_yday - b-> tm_yday
/* + intervening leap days */
+ (( ay >> 2) - ( by >> 2))
- ( ay / 100 - by / 100) + (( ay / 100 >> 2) - ( by / 100 >> 2))
/* + difference in years * 365 */
+ ( long) ( ay - by) * 365);
  return (60 * (60 * (24 * days + ( a-> tm_hour - b-> tm_hour))
+ ( a-> tm_min - b-> tm_min)) + ( a-> tm_sec - b-> tm_sec));
}

time_t get_timestamp ( const char * date) {
  struct tm tm, tm0, * tmp;
  time_t Start;

  if ( date == NULL) {
      return time( NULL);
  }

  parse_date_Input = date;
  Start = time( NULL);
  tmp = localtime(& Start);
  if (! tmp)
    return -1;
  parse_date_Year = tmp-> tm_year + TM_YEAR_ORIGIN;
  parse_date_Month = tmp-> tm_mon + 1;
  parse_date_Day = tmp-> tm_mday;
  parse_date_Hour = tmp-> tm_hour;
  parse_date_Minutes = tmp-> tm_min;
  parse_date_Seconds = tmp-> tm_sec;
  tm. tm_isdst = tmp-> tm_isdst;
  parse_date_Meridian = MER24;
  parse_date_RelSeconds = 0;
  parse_date_RelMinutes = 0;
  parse_date_RelHour = 0;
  parse_date_RelDay = 0;
  parse_date_RelMonth = 0;
  parse_date_RelYear = 0;
  parse_date_HaveDate = 0;
  parse_date_HaveDay = 0;
  parse_date_HaveRel = 0;
  parse_date_HaveTime = 0;
  parse_date_HaveZone = 0;

  if ( parse_date ()
      || parse_date_HaveTime > 1 || parse_date_HaveZone > 1
      || parse_date_HaveDate > 1 || parse_date_HaveDay > 1)
    return -1;

  tm. tm_year = ToYear ( parse_date_Year) - TM_YEAR_ORIGIN + parse_date_RelYear;
  tm. tm_mon = parse_date_Month - 1 + parse_date_RelMonth;
  tm. tm_mday = parse_date_Day + parse_date_RelDay;
  if ( parse_date_HaveTime
      || ( parse_date_HaveRel && ! parse_date_HaveDate
  && ! parse_date_HaveDay)) {
    tm. tm_hour = ToHour ( parse_date_Hour, parse_date_Meridian);
    if ( tm. tm_hour < 0)
      return -1;
    tm. tm_min = parse_date_Minutes;
    tm. tm_sec = parse_date_Seconds;
  }
  else {
    tm. tm_hour = tm. tm_min = tm. tm_sec = 0;
  }
  tm. tm_hour += parse_date_RelHour;
  tm. tm_min += parse_date_RelMinutes;
  tm. tm_sec += parse_date_RelSeconds;

  if ( parse_date_HaveDate | parse_date_HaveDay | parse_date_HaveTime |
      parse_date_RelDay | parse_date_RelMonth | parse_date_RelYear)
    tm. tm_isdst = -1;

  tm0 = tm;

  Start = mktime (& tm);

  if ( Start == ( time_t) - 1) {

    /* Guard against falsely reporting errors near the time_t boundaries
       when parsing times in other time zones.  For example, if the min
       time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
       of UTC, then the min localtime value is 1970-01-01 08:00:00; if
       we apply mktime to 1970-01-01 00:00:00 we will get an error, so
       we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
       zone by 24 hours to compensate.  This algorithm assumes that
       there is no DST transition within a day of the time_t boundaries.  */

    if ( parse_date_HaveZone) {
      tm = tm0;
      if ( tm. tm_year <= EPOCH - TM_YEAR_ORIGIN) {
tm. tm_mday++;
parse_date_Timezone -= 24 * 60;
      }
      else {
tm. tm_mday--;
parse_date_Timezone += 24 * 60;
      }
      Start = mktime (& tm);
    }

    if ( Start == ( time_t) - 1)
      return Start;
  }

  if ( parse_date_HaveDay && ! parse_date_HaveDate) {
    tm. tm_mday += (( parse_date_DayNumber - tm. tm_wday + 7) % 7
   + 7 * ( parse_date_DayOrdinal -
  (0 < parse_date_DayOrdinal)));
    Start = mktime (& tm);
    if ( Start == ( time_t) - 1)
      return Start;
  }

  if ( parse_date_HaveZone) {
    long delta;
    struct tm * gmt = gmtime (& Start);
    if (! gmt)
      return -1;
    delta = parse_date_Timezone * 60L + difftm (& tm, gmt);
    if (( Start + delta < Start) != ( delta < 0))
      return -1; /* time_t overflow */
    Start += delta;
  }

  return Start;
}

转载于:https://www.cnblogs.com/fx2008/archive/2011/09/27/2193011.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值