⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbx_date.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  Date.c  The date & time management routines  Code adapted from GLib 1.2.8  (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net>  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __DATE_C#include <unistd.h>#include <ctype.h>#include "gb_common.h"#include "gb_common_buffer.h"#include "gb_error.h"#include "gbx_value.h"#include "gbx_local.h"#include "gbx_number.h"#include "gbx_date.h"/*#define DEBUG_DATE*/static const char days_in_months[2][13] ={  /* error, jan feb mar apr may jun jul aug sep oct nov dec */  {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },  {  0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* leap year */};static const short days_in_year[2][14] ={  /* 0, jan feb mar apr may  jun  jul  aug  sep  oct  nov  dec */  {  0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },  {  0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }  /* leap year */};static long date_timezone;static int date_daylight;static double _start_time;/* Returns 1 for a leap year, 0 else */static int date_is_leap_year(short year){  if (year < 0)    year += 8001;  if ((((year % 4) == 0) && ((year % 100) != 0)) || (year % 400) == 0)    return 1;  else    return 0;}static boolean date_is_valid(DATE_SERIAL *date){  return ((date->month >= 1) && (date->month <= 12) &&          (date->year >= DATE_YEAR_MIN) && (date->year <= DATE_YEAR_MAX) && (date->year != 0) &&          (date->day >= 1) && (date->day <= days_in_months[date_is_leap_year(date->year)][(short)date->month]) &&          (date->hour >= 0) && (date->hour <= 23) && (date->min >= 0) && (date->min <= 59) &&          (date->sec >= 0) && (date->sec <= 59));}static short date_to_julian_year(short year){  if (year < 0)    return year - DATE_YEAR_MIN;  else    return year - DATE_YEAR_MIN - 1;}static short date_from_julian_year(short year){  if (year < (-DATE_YEAR_MIN))    return year + DATE_YEAR_MIN;  else    return year + DATE_YEAR_MIN + 1;}PUBLIC void DATE_init(void){  time_t t = (time_t)0L;  struct tm *tm;  struct timeval tv;  if (gettimeofday(&tv, NULL) == 0)    _start_time = (double)tv.tv_sec + (double)tv.tv_usec / 1E6;  else    _start_time = 0.0;  tm = localtime(&t);  #ifdef __FreeBSD__  date_timezone = tm->tm_gmtoff;  date_daylight = tm->tm_isdst;  #else  date_timezone = timezone;  date_daylight = daylight;  #endif  #ifdef DEBUG_DATE  printf("TimeZone = %ld DayLight = %d Hour = %d\n", date_timezone, date_daylight, tm->tm_hour);  tm = gmtime(&t);  printf("Hour = %d\n", tm->tm_hour);  #endif}PUBLIC DATE_SERIAL *DATE_split(VALUE *value){  static long last_nday, last_nmsec;  static DATE_SERIAL last_date = { 0 };  long nday, nmsec;  long A, B, C, D, E, M;  nday = value->_date.date;  nmsec = value->_date.time;  if (nday > 0)    nmsec += date_timezone * 1000;  if (nmsec < 0)  {    nday--;    nmsec += 86400000;  }  else if (nmsec >= 86400000)  {    nday++;    nmsec -= 86400000;  }  if (last_nmsec != nmsec)  {    last_nmsec = nmsec;    last_date.msec = nmsec % 1000;    nmsec /= 1000;    last_date.sec = nmsec % 60;    nmsec /= 60;    last_date.min = nmsec % 60;    nmsec /= 60;    last_date.hour = nmsec;  }  if (last_nday != nday)  {    last_nday = nday;    /*nday += DATE_NDAY_BC;*/    if (nday <= 0)    {      last_date.month = 0;      last_date.day = 0;      last_date.year = 0;      last_date.weekday = 0;    }    else    {      A = nday - 58 - 1;      B = (4 * (A + 36524))/ 146097 - 1;      C = A - (146097 * B)/4;      D = (4 * (C + 365)) / 1461 - 1;      E = C - ((1461 * D) / 4);      M = (5 * (E - 1) + 2) / 153;      last_date.month = M + 3 - (12 * (M / 10));      last_date.day = E - (153 * M + 2)/5;      last_date.year = 100 * B + D + (M / 10) /*- 4800*/ ;      last_date.year = date_from_julian_year(last_date.year);      last_date.weekday = (nday - 1) % 7;    }  }  return &last_date;}PUBLIC bool DATE_make(DATE_SERIAL *date, VALUE *val){  short year;  long nday;  bool timezone;  if (date->year == 0)  {    nday = 0; /*(-DATE_NDAY_BC - 1);*/    timezone = FALSE;  }  else  {    if (!date_is_valid(date))      return TRUE;    year = date_to_julian_year(date->year);    nday = year * 365;    year--;    nday += (year >>= 2);    nday -= (year /= 25);    nday += year >> 2;    nday += days_in_year[date_is_leap_year(date->year)][(short)date->month] + date->day;    /*nday -= DATE_NDAY_BC;*/    timezone = TRUE;  }  val->_date.date = nday;  val->_date.time = ((date->hour * 60) + date->min) * 60 + date->sec;  if (timezone)    val->_date.time -= date_timezone;  if (val->_date.time < 0)  {    val->_date.date--;    val->_date.time += 86400;  }  else if (val->_date.time >= 86400)  {    val->_date.date++;    val->_date.time -= 86400;  }  val->_date.time = (val->_date.time * 1000) + date->msec;  val->type = T_DATE;    return FALSE;}/*struct tm      {              int     tm_sec;              int     tm_min;              int     tm_hour;              int     tm_mday;         quanti鑝e du mois              int     tm_mon;              int     tm_year;              int     tm_wday;         jour de la semaine              int     tm_yday;         jour de l'ann閑              int     tm_isdst;        d閏alage horaire      };*/static int get_current_year(void){  struct tm *tm;  struct timeval tv;  if (gettimeofday(&tv, NULL) != 0)    THROW(E_DATE);  tm = localtime((time_t *)&tv.tv_sec);  return tm->tm_year + 1900;}PUBLIC void DATE_from_time(time_t time, long usec, VALUE *val){  struct tm *tm;  DATE_SERIAL date;  tm = localtime(&time);  date.year = tm->tm_year + 1900;  date.month = tm->tm_mon + 1;  date.day = tm->tm_mday;  date.hour = tm->tm_hour;  date.min = tm->tm_min;  date.sec = tm->tm_sec;  date.msec = usec / 1000;  if (DATE_make(&date, val))    val->type = T_NULL;}PUBLIC void DATE_now(VALUE *val){  struct timeval tv;  if (gettimeofday(&tv, NULL) != 0)    val->type = T_NULL;  else    DATE_from_time((time_t)tv.tv_sec, tv.tv_usec, val);}PUBLIC int DATE_to_string(char *buffer, VALUE *value){  DATE_SERIAL *date;  int len;  date = DATE_split(value);  if (value->_date.date == 0)    len = sprintf(buffer,"%02d:%02d:%02d", date->hour, date->min, date->sec);  else if ((date->hour | date->min | date->sec | date->msec) == 0)    len = sprintf(buffer,"%02d/%02d/%04d", date->month, date->day, date->year);  else    len = sprintf(buffer,"%02d/%02d/%04d %02d:%02d:%02d", date->month, date->day, date->year, date->hour, date->min, date->sec);    if (date->msec)  {    len += sprintf(&buffer[len], ".%03d", date->msec);    while (buffer[len - 1] == '0')      len--;    buffer[len] = 0;  }    return len;}static boolean read_integer(int *number){  int nbr = 0;  int nbr2;  int c;  boolean minus = FALSE;  c = get_char();  if (c == '-')  {    minus = TRUE;    c = get_char();  }  else if (c == '+')    c = get_char();  if ((c < 0) || !isdigit(c))    return TRUE;  for(;;)  {    nbr2 = nbr * 10 + (c - '0');    if (nbr2 < nbr)      return TRUE;    nbr = nbr2;    c = look_char();    if ((c < 0) || !isdigit(c))      break;    buffer_pos++;  }  *number = nbr;  return FALSE;}static boolean read_msec(int *number){  int nbr = 0;  int nbr2;  int c;  int i;  c = get_char();  if ((c < 0) || !isdigit(c))    return TRUE;  i = 0;  for(;;)  {    i++;    nbr2 = nbr * 10 + (c - '0');    if (nbr2 < nbr)      return TRUE;    nbr = nbr2;        if (i == 3)      break;    c = look_char();    if ((c < 0) || !isdigit(c))      break;    buffer_pos++;  }    for (; i < 3; i++)    nbr *= 10;  *number = nbr;  return FALSE;}static void set_date(DATE_SERIAL *date, int which, int value){  if (which == LO_YEAR)  {    if (value >= 0 && value <= 99)    {      if (value > 30)        value += 1900;      else        value += 2000;    }    date->year = value;  }  else if (which == LO_MONTH)    date->month = value;  else if (which == LO_DAY)    date->day = value;}static void set_time(DATE_SERIAL *date, int which, int value){  if (which == LO_HOUR)    date->hour = value;  else if (which == LO_MINUTE)    date->min = value;  else if (which == LO_SECOND)    date->sec = value;}PUBLIC boolean DATE_from_string(const char *str, long len, VALUE *val, boolean local){  DATE_SERIAL date;  LOCAL_INFO *info = LOCAL_get(local);  int nbr, nbr2;  int c, i;  boolean has_date = FALSE;  boolean has_time = FALSE;  CLEAR(&date);  buffer_init(str, len);  jump_space();  if (read_integer(&nbr))    return TRUE;  c = get_char();  if (c == info->date_sep)  {    has_date = TRUE;    if (read_integer(&nbr2))      return TRUE;    c = get_char();    if ((c < 0) || isspace(c))    {      i = 0;      set_date(&date, LO_YEAR, get_current_year());      if (info->date_order[i] == LO_YEAR) i++;      set_date(&date, info->date_order[i], nbr); i++;      if (info->date_order[i] == LO_YEAR) i++;      set_date(&date, info->date_order[i], nbr2);    }    else if (c == info->date_sep)    {      set_date(&date, info->date_order[0], nbr);      set_date(&date, info->date_order[1], nbr2);      if (read_integer(&nbr))        return TRUE;      set_date(&date, info->date_order[2], nbr);    }    jump_space();    c = look_char();    if (c < 0)      goto _OK;    if (read_integer(&nbr))      return TRUE;    c = get_char();  }  if (c == info->time_sep)  {    has_time = TRUE;    if (read_integer(&nbr2))      return TRUE;    c = get_char();    if ((c < 0) || isspace(c))    {      i = 0;      if (info->time_order[i] == LO_SECOND) i++;      set_time(&date, info->time_order[i], nbr); i++;      if (info->time_order[i] == LO_SECOND) i++;      set_time(&date, info->time_order[i], nbr2);    }    else if (c == info->time_sep)    {      set_time(&date, info->time_order[0], nbr);      set_time(&date, info->time_order[1], nbr2);      if (read_integer(&nbr))        return TRUE;      set_time(&date, info->time_order[2], nbr);          c = get_char();          if (c == '.') // msec separator      {        if (read_msec(&nbr))          return TRUE;        date.msec = nbr;      }    }    c = get_char();    if ((c < 0) || isspace(c))      goto _OK;  }  return TRUE;_OK:  if (DATE_make(&date, val))    return TRUE;  if (!has_date)    val->_date.date = 0;  return FALSE;}PUBLIC int DATE_comp(DATE *date1, DATE *date2){  if (date1->date < date2->date)    return (-1);  if (date1->date > date2->date)    return 1;  if (date1->time < date2->time)    return (-1);  if (date1->time > date2->time)    return 1;  return 0;}PUBLIC int DATE_comp_value(VALUE *date1, VALUE *date2){  return DATE_comp((DATE *)&date1->_date.date, (DATE *)&date2->_date.date);}PUBLIC bool DATE_timer(double *result, int from_start){  struct timeval tv;  *result = 0;  if (gettimeofday(&tv, NULL) == 0)  {    *result = (double)tv.tv_sec + (double)tv.tv_usec / 1E6;    if (from_start)      *result -= _start_time;    return FALSE;  }  else    return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -