{"action":"created","comment":{"url":"https://api.github.com/repos/cesanta/v7/pulls/comments/24926893","id":24926893,"diff_hunk":"@@ -1,18 +1,981 @@\n /*\n- * Copyright (c) 2014 Cesanta Software Limited\n+ * Copyright (c) 2015 Cesanta Software Limited\n  * All rights reserved\n  */\n \n #include \"internal.h\"\n+#include <sys/time.h>\n+#include <time.h>\n+#include <math.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <locale.h>\n+#include <stddef.h>\n \n-V7_PRIVATE enum v7_err Date_ctor(struct v7_c_func_arg *cfa) {\n-  struct v7_val *obj = cfa->called_as_constructor ? cfa->this_obj :\n-                       v7_push_new_object(cfa->v7);\n-  v7_set_class(obj, V7_CLASS_DATE);\n-  return V7_OK;\n+#ifdef __APPLE__\n+int64_t strtoll(const char *, char **, int);\n+#else\n+extern long timezone;\n+extern struct tm *getdate(const char *);\n+#endif\n+\n+typedef double etime_t; /* double is suitable type for ECMA time */\n+/* inernally we have to use 64-bit integer for some operations */\n+typedef int64_t etimeint_t;\n+#define INVALID_TIME NAN\n+\n+/*++++++  ECMA date & time helpers ++++++*/\n+\n+#define msPerDay 86400000\n+#define HoursPerDay 24\n+#define MinutesPerHour 60\n+#define SecondsPerMinute 60\n+#define SecondsPerHour 3600\n+#define msPerSecond 1000\n+#define msPerMinute 60000\n+#define msPerHour 3600000\n+#define MonthsInYear 12\n+\n+static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */\n+static const char* g_tzname; /* current timezone name */\n+\n+static etimeint_t ecma_Day(etime_t t) {\n+  return floor(t/ msPerDay);\n+}\n+\n+/* Leap year formula copied from ECMA 5.1 standart as is */\n+static int ecma_DaysInYear(int y) {\n+  if(y % 4 != 0 ) {\n+    return 365;\n+  } else if( y % 4 == 0 && y % 100 != 0 ) {\n+    return 366;\n+  } else if(y % 100 == 0 && y % 400 != 0) {\n+    return 365;\n+  } else if(y % 400 == 0) {\n+    return 366;\n+  } else {\n+    return 365;\n+  }\n+}\n+\n+static etimeint_t ecma_DayFromYear(etimeint_t y) {\n+  return 365 * (y-1970) + floor((y-1969)/4) - floor((y-1901)/100)\n+                                              + floor((y-1601)/400);\n+}\n+\n+static etimeint_t ecma_TimeFromYear(etimeint_t y) {\n+  return msPerDay * ecma_DayFromYear(y);\n+}\n+\n+static int ecma_YearFromTime_s(etime_t t)\n+{\n+  int first = floor((t / msPerDay) / 366) + 1970,\n+              last = floor((t / msPerDay) / 365) + 1970,\n+              middle = 0;\n+  \n+  if (last < first) {\n+    int temp = first;\n+    first = last;\n+    last = temp;\n+  }\n+  \n+  while (last > first) {\n+    middle = (last + first) / 2;\n+    if (ecma_TimeFromYear(middle) > t) {\n+      last = middle - 1;\n+    } else {\n+      if (ecma_TimeFromYear(middle) <= t) {\n+        if (ecma_TimeFromYear(middle + 1) > t) {\n+          first = middle;\n+          break;\n+        }\n+        first = middle + 1;\n+      }\n+    }\n+  }\n+  \n+  return first;\n+}\n+\n+static int ecma_IsLeapYear(int year) {\n+  return ecma_DaysInYear(year) == 366;\n+}\n+\n+static int ecma_DayWithinYear(etime_t t, int year) {\n+  return (int)(ecma_Day(t) - ecma_DayFromYear(year));\n+}\n+\n+static int* ecma_getfirstdays(int isleap) {\n+  static int sdays[2][MonthsInYear+1] =\n+    {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},\n+     {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};\n+  \n+  return sdays[isleap];\n+}\n+\n+static int ecma_MonthFromTime(etime_t t, int year) {\n+  int *days;\n+  etimeint_t dwy = ecma_DayWithinYear(t, year);\n+  \n+  unsigned int i;\n+  \n+  days = ecma_getfirstdays(ecma_IsLeapYear(year));\n+  \n+  for(i = 0; i < MonthsInYear; i++) {\n+    if(dwy >= days[i] && dwy < days[i+1]) {\n+      return i;\n+    }\n+  }\n+  \n+  return -1;\n+}\n+\n+static int ecma_DateFromTime(etime_t t, int year) {\n+  int *days;\n+  int mft = ecma_MonthFromTime(t, year);\n+  int dwy = ecma_DayWithinYear(t, year);\n+  \n+  if(mft > 11) {\n+    return -1;\n+  }\n+  \n+  days = ecma_getfirstdays(ecma_IsLeapYear(year));\n+  \n+  return dwy - days[mft] + 1;\n+}\n+\n+static int ecma_WeekDay(etime_t t) {\n+  int ret = (ecma_Day(t)+4) % 7;\n+  if(ret < 0) {\n+    ret += 7;\n+  }\n+\n+  return ret;\n+}\n+\n+static int ecma_DaylightSavingTA(etime_t t) {\n+  time_t time = t / 1000;\n+  struct tm tm;\n+  memset(&tm, 0, sizeof(t));\n+  localtime_r(&time, &tm);\n+  if(tm.tm_isdst > 0) {\n+    return msPerHour;\n+  } else {\n+    return 0;\n+  }\n+}\n+\n+static int ecma_LocalTZA() {\n+  return (int)-g_gmtoffms;\n+}\n+\n+static etimeint_t ecma_LocalTime(etime_t t) {\n+  return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t);\n+}\n+\n+static etimeint_t ecma_UTC(etime_t t) {\n+  return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t-ecma_LocalTZA());\n+}\n+\n+#define DEF_EXCTRACT_TIMEPART(funcname, c1, c2) \\\n+  static int ecma_##funcname(etime_t t) { \\\n+    int ret = (etimeint_t)floor( t / c1) % c2; \\\n+    if(ret < 0) { \\\n+      ret += c2; \\\n+    } \\\n+    return ret; \\\n+  }\n+\n+DEF_EXCTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay)\n+DEF_EXCTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour)\n+DEF_EXCTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute)\n+DEF_EXCTRACT_TIMEPART(msFromTime, 1, msPerSecond)\n+\n+\n+static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min,\n+                                    etimeint_t sec, etimeint_t ms) {\n+  return ((hour * MinutesPerHour + min)\n+                      * SecondsPerMinute + sec) * msPerSecond + ms;\n+}\n+\n+static etimeint_t ecma_MakeDay(int year, int month, int date)\n+{\n+  int *days;\n+\n+  etimeint_t yday;\n+  etimeint_t mday;\n+  \n+  year += floor(month / 12);\n+  \n+  month = month % 12;\n+  \n+  yday = floor(ecma_TimeFromYear(year) / msPerDay);\n+\n+  days = ecma_getfirstdays(ecma_IsLeapYear(year));\n+\n+  mday = days[month];\n+  \n+  return yday + mday + date - 1;\n+}\n+\n+static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) {\n+  return (day * msPerDay + time);\n+}\n+\n+/*++++ ECMA alternatives to struct tm ++++*/\n+\n+struct timeparts {\n+  int year; /* can be negative, up to +-282000 */\n+  int month; /* 0-11 */\n+  int day; /* 1-31 */\n+  int hour; /* 0-23 */\n+  int min; /* 0-59 */\n+  int sec; /* 0-59 */\n+  int msec; \n+  int dayofweek; /* 0-6 */\n+};\n+\n+/*+++ this functions is used to get current date/time & timezone */\n+\n+static void d_gettime(etime_t *time) {\n+  struct timeval tv;\n+  gettimeofday(&tv, NULL);\n+  *time = (etime_t)tv.tv_sec * 1000 + (etime_t)tv.tv_usec / 1000;\n+}\n+\n+static const char* d_gettzname() {\n+  return g_tzname;\n+}\n+\n+static etime_t d_mktime_impl(const struct timeparts *tp) {\n+  return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day),\n+                       ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec));\n+}\n+\n+/*++++ libc mktime alternatives ++++*/\n+\n+static etime_t d_lmktime(const struct timeparts *tp) {\n+  return ecma_UTC(d_mktime_impl(tp));\n+}\n+\n+static etime_t d_gmktime(const struct timeparts *tp) {\n+  return d_mktime_impl(tp);\n+}\n+\n+typedef etime_t (*fmaketime)(const struct timeparts* );\n+\n+/*++++ libc gmtime & localtime alternatives ++++*/\n+static void d_gmtime(const etime_t *t, struct timeparts *tp) {\n+  tp->year = ecma_YearFromTime_s(*t);\n+  tp->month = ecma_MonthFromTime(*t, tp->year);\n+  tp->day = ecma_DateFromTime(*t, tp->year);\n+  tp->hour = ecma_HourFromTime(*t);\n+  tp->min = ecma_MinFromTime(*t);\n+  tp->sec = ecma_SecFromTime(*t);\n+  tp->msec = ecma_msFromTime(*t);\n+  tp->dayofweek = ecma_WeekDay(*t);\n+}\n+\n+static void d_localtime(const etime_t* time, struct timeparts *tp) {\n+  etime_t local_time = ecma_LocalTime(*time);\n+  d_gmtime(&local_time, tp);\n+}\n+\n+typedef void (*fbreaktime)(const etime_t* , struct timeparts* );\n+\n+/*++++ some isXXX helpers ++++*/\n+static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) {\n+  val_t ret = i_value_of(v7, obj);\n+  if (ret == V7_TAG_NAN) {\n+    throw_exception(v7, \"TypeError\", \"Date is invalid (for string)\");\n+  }\n+  return ret;\n+}\n+\n+static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) {\n+  /* TODO(alashkin): verify this statement */\n+  return is_prototype_of(this_obj, v7->date_prototype);\n+}\n+\n+/*++++ from/to string helpers ++++*/\n+\n+static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) {\n+  /* ISO format: \"+XXYYYY-MM-DDTHH:mm:ss.sssZ\"; */\n+  struct timeparts tp;\n+  char use_ext = 0;\n+  const char* ey_frm=\"%06d-%02d-%02dT%02d:%02d:%02d.%03dZ\";\n+  const char* simpl_frm=\"%d-%02d-%02dT%02d:%02d:%02d.%03dZ\";\n+  \n+  d_gmtime(time, &tp);\n+\n+  if(abs(tp.year) > 9999 || tp.year < 0) {\n+    *buf = tp.year>0? '+':'-';\n+    use_ext = 1;\n+  }\n+  \n+  return snprintf(buf + use_ext, buf_size - use_ext, \n+        use_ext? ey_frm: simpl_frm, abs(tp.year), tp.month + 1,\n+                    tp.day, tp.hour, tp.min, tp.sec, tp.msec) + use_ext;\n+}\n+\n+/* non-locale function should always return in english and 24h-format */\n+static const char* wday_name[] = {\n+  \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"\n+};\n+\n+static const char* mon_name[] = {\n+  \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n+  \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"\n+};\n+\n+int d_getnumbyname(const char **arr, int arr_size, const char *str) {\n+  int i;\n+  for(i = 0; i < arr_size; i++) {\n+    if(strncmp(arr[i], str, 3) == 0 ) {\n+      return i + 1;\n+    }\n+  }\n+  \n+  return -1;\n+}\n+\n+int date_parse(const char *str, int *a1, int *a2, int *a3, char\n+                                                    sep, char *rest) {\n+  char frmDate[] = \" %d/%d/%d%[^\\0]\";\n+  frmDate[3] = frmDate[6] = sep;\n+  return sscanf(str, frmDate, a1, a2, a3, rest);\n+}\n+\n+#define NO_TZ 0x7FFFFFFF\n+\n+/* not very smart but simple, and working according \n+                                    to ECMA5.1 StringToDate function */\n+static int d_parsedatestr(const char *str, struct timeparts *tp, int *tz) {\n+  char gmt[4];\n+  char buf1[100] = {0}, buf2[100] = {0};\n+  int res = 0;\n+  memset(tp, 0, sizeof(*tp));\n+  *tz = NO_TZ;\n+  \n+  /* #1: trying toISOSrting() format */\n+  {\n+    const char* frmISOString = \" %d-%02d-%02dT%02d:%02d:%02d.%03dZ\";\n+    res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day,\n+                                &tp->hour, &tp->min, &tp->sec, &tp->msec);\n+    if(res == 7) {\n+      *tz = 0;\n+      return 1;\n+    }\n+  }\n+  \n+  /* #2: trying getdate() - it never works on some OS, but... */\n+  {\n+    struct tm *tm = getdate(str);\n+    if(tm != NULL) {\n+      tp->year = tm->tm_year + 1900;\n+      tp->month = tm->tm_mon;\n+      tp->day = tm->tm_mday;\n+      tp->hour = tm->tm_hour;\n+      tp->min = tm->tm_min;\n+      tp->sec = tm->tm_sec;\n+    \n+      return 1;\n+    }\n+  }\n+  \n+  /* #3: trying toString()/toUTCString()/toDateFormat() formats */\n+  {\n+    char month[4];\n+    const char* frmString = \" %03*s %03s %02d %d %02d:%02d:%02d %03s%d\";\n+    res = sscanf(str, frmString, month, &tp->day, &tp->year, &tp->hour,\n+                                            &tp->min, &tp->sec, gmt, tz);\n+    if(res == 3 || (res >= 6 && res <= 8) ) {\n+      if( (tp->month = d_getnumbyname(mon_name,\n+                                      ARRAY_SIZE(mon_name), month)) != -1) {\n+        if(res == 7 && strncmp(gmt, \"GMT\", 3) == 0 ) {\n+          *tz = 0;\n+        }\n+        return 1;\n+      }\n+    }\n+  }\n+  \n+  /* #4: trying the rest */\n+  \n+  /* trying date */\n+\n+  if(!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 ||\n+       date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 ||\n+       date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3 ) ) {\n+    return 0;\n+  }\n+  \n+  /*  there is date, trying time; from here return 0 only on errors */\n+  \n+  /* trying HH:mm */\n+  {\n+    const char* frmMMhh = \" %d:%d%[^\\0]\";\n+    res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2);\n+    /* can't get time, but have some symbols, assuming error */\n+    if(res < 2 ) {\n+      return (strlen(buf2) == 0);\n+    }\n+  }\n+  \n+  /* trying seconds */\n+  {\n+    const char* frmss = \":%d%[^\\0]\";\n+    memset(buf1, 0, sizeof(buf1));\n+    res = sscanf(buf2, frmss, &tp->sec, buf1);\n+  }\n+  \n+  /* even if we don't get seconds we gonna try to get tz */\n+  {\n+    char* rest = res? buf1: buf2;\n+    char* buf = res? buf2: buf1;\n+    const char* frmtz = \" %03s%d%[^\\0]\";\n+    \n+    res = sscanf(rest, frmtz, gmt, tz, buf);\n+    if(res == 1 && strncmp(gmt, \"GMT\", 3) == 0) {\n+      *tz = 0;\n+    }\n+  }\n+\n+  /* return OK if we are at the end of string */\n+  return (res <= 2);\n+}\n+\n+static int d_timeFromString(etime_t *time, const char *str, size_t buf_size) {\n+  struct timeparts tp;\n+  int tz;\n+  \n+  *time = INVALID_TIME;\n+  \n+  if(buf_size > 100) {\n+    /* too long for valid date string */\n+    return 0;\n+  }\n+  \n+  if(d_parsedatestr(str, &tp, &tz)) {\n+    /* check results */\n+    int valid = 0;\n+    \n+    tp.month--;\n+    valid = tp.day >=1 && tp.day <= 31;\n+    valid &= tp.month >=0 && tp.month <= 11;\n+    valid &= tp.hour >= 0 && tp.hour <= 23;\n+    valid &= tp.min >= 0 && tp.min <= 59;\n+    valid &= tp.sec >= 0 && tp.sec <= 59;\n+    \n+    if(tz != NO_TZ && tz > 12) {\n+      tz /= 100;\n+    }\n+    \n+    valid &= (abs(tz) <= 12 || tz == NO_TZ);\n+    \n+    if(valid) {\n+      *time = d_gmktime(&tp);\n+\n+      if(tz != NO_TZ) {\n+        /* timezone specified, use it */\n+        *time -= tz * msPerHour;\n+      } else if(tz != 0 ) {\n+        /* assuming local timezone and moving back to UTC */\n+        *time = ecma_UTC(*time);\n+      }\n+    }\n+  }\n+\n+  return !isnan(*time);\n+}\n+\n+typedef int (*ftostring)(const struct timeparts*, char*, int);\n+\n+static val_t d_tostring(struct v7 *v7, val_t obj, fbreaktime breaktimefunc,\n+                                        ftostring tostringfunc, int addtz) {\n+  struct timeparts tp;\n+  int len;\n+  char buf[100];\n+  etime_t time;\n+  \n+  time = v7_to_double(d_trytogetobjforstring(v7, obj));\n+  \n+  breaktimefunc(&time, &tp);\n+  len = tostringfunc(&tp, buf, addtz);\n+  \n+  return v7_create_string(v7, buf, len, 1);\n+}\n+\n+struct d_locale {\n+  char locale[50];\n+};\n+\n+static void d_getcurrentlocale(struct d_locale *loc) {\n+  strcpy(setlocale(LC_TIME, 0), loc->locale);\n+}\n+\n+static void d_setlocale(const struct d_locale *loc) {\n+  setlocale(LC_TIME, loc? loc->locale: \"\");\n+}\n+\n+/* TODO(alashkin): check portability */\n+static val_t d_tolocalestr(struct v7 *v7, val_t obj, const char *frm) {\n+  char buf[250];\n+  size_t len;\n+  struct tm t;\n+  etime_t time;\n+  struct d_locale prev_locale;\n+  struct timeparts tp;\n+\n+  time = v7_to_double(d_trytogetobjforstring(v7, obj));\n+  \n+  d_getcurrentlocale(&prev_locale);\n+  d_setlocale(0);\n+\n+  d_localtime(&time, &tp);\n+\n+  memset(&t, 0, sizeof(t));\n+  t.tm_year = tp.year - 1900;\n+  t.tm_mon = tp.month;\n+  t.tm_mday = tp.day;\n+  t.tm_hour = tp.hour;\n+  t.tm_min = tp.min;\n+  t.tm_sec = tp.sec;\n+  t.tm_wday = tp.dayofweek;\n+\n+  len = strftime(buf, sizeof(buf), frm, &t);\n+  \n+  d_setlocale(&prev_locale);\n+  \n+  return v7_create_string(v7, buf, len, 1);\n+}\n+\n+static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) {\n+  (void)addtz;\n+\n+  return sprintf(buf, \"%s %s %02d %d\", wday_name[tp->dayofweek],\n+                                    mon_name[tp->month], tp->day, tp->year);\n+}\n+\n+static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) {\n+  int len;\n+\n+  len = sprintf(buf, \"%02d:%02d:%02d GMT\", tp->hour, tp->min, tp->sec);\n+  \n+  if(addtz && g_gmtoffms != 0) {\n+    len = sprintf(buf+len, \"%c%02d00 (%s)\", g_gmtoffms > 0? '-':'+',\n+                                abs((int)g_gmtoffms/msPerHour), d_gettzname());\n+  }\n+  \n+  return (int)strlen(buf);\n+}\n+\n+static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) {\n+  int len = d_tptodatestr(tp, buf, addtz);\n+  *(buf + len) = ' ';\n+  return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1;\n+}\n+\n+/*+++ setXXXX & getXXXX helpers ++++*/\n+static struct timeparts* d_getTP(val_t val,  struct timeparts *tp,\n+                                              fbreaktime breaktimefunc) {\n+  etime_t time;\n+  time = v7_to_double(val);\n+  breaktimefunc(&time, tp);\n+  return tp;\n+}\n+\n+/* notice: holding month in calendar format (1-12, not 0-11) */\n+struct dtimepartsarr {\n+  etime_t args[7];\n+};\n+\n+enum detimepartsarr { tpyear = 0, tpmonth , tpdate , tphours, tpminutes,\n+                                                  tpseconds, tpmsec, tpmax };\n+\n+static etime_t d_changepartoftime(const etime_t *current,\n+                            struct dtimepartsarr *a, fbreaktime breaktimefunc,\n+                                            fmaketime maketimefunc) {\n+  /* 0 = year, 1 = month , 2 = date , 3 = hours, \n+                4 = minutes, 5 = seconds, 6 = ms */\n+  struct timeparts tp;\n+  unsigned long i;\n+  \n+  int* tp_arr[7]; /* C89 doesn't handle initialization ","path":"src/date.c","position":611,"original_position":611,"commit_id":"ec6f400a91fc5432dab30527e0839c02281262cd","original_commit_id":"ec6f400a91fc5432dab30527e0839c02281262cd","user":{"login":"alashkin","id":5459304,"avatar_url":"https://avatars.githubusercontent.com/u/5459304?v=3","gravatar_id":"","url":"https://api.github.com/users/alashkin","html_url":"https://github.com/alashkin","followers_url":"https://api.github.com/users/alashkin/followers","following_url":"https://api.github.com/users/alashkin/following{/other_user}","gists_url":"https://api.github.com/users/alashkin/gists{/gist_id}","starred_url":"https://api.github.com/users/alashkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alashkin/subscriptions","organizations_url":"https://api.github.com/users/alashkin/orgs","repos_url":"https://api.github.com/users/alashkin/repos","events_url":"https://api.github.com/users/alashkin/events{/privacy}","received_events_url":"https://api.github.com/users/alashkin/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2015-02-18T18:34:36Z","updated_at":"2015-02-18T18:34:36Z","html_url":"https://github.com/cesanta/v7/pull/260#discussion_r24926893","pull_request_url":"https://api.github.com/repos/cesanta/v7/pulls/260","_links":{"self":{"href":"https://api.github.com/repos/cesanta/v7/pulls/comments/24926893"},"html":{"href":"https://github.com/cesanta/v7/pull/260#discussion_r24926893"},"pull_request":{"href":"https://api.github.com/repos/cesanta/v7/pulls/260"}}},"pull_request":{"url":"https://api.github.com/repos/cesanta/v7/pulls/260","id":29389064,"html_url":"https://github.com/cesanta/v7/pull/260","diff_url":"https://github.com/cesanta/v7/pull/260.diff","patch_url":"https://github.com/cesanta/v7/pull/260.patch","issue_url":"https://api.github.com/repos/cesanta/v7/issues/260","number":260,"state":"open","locked":false,"title":"15.9 Date Objects - implementation","user":{"login":"alashkin","id":5459304,"avatar_url":"https://avatars.githubusercontent.com/u/5459304?v=3","gravatar_id":"","url":"https://api.github.com/users/alashkin","html_url":"https://github.com/alashkin","followers_url":"https://api.github.com/users/alashkin/followers","following_url":"https://api.github.com/users/alashkin/following{/other_user}","gists_url":"https://api.github.com/users/alashkin/gists{/gist_id}","starred_url":"https://api.github.com/users/alashkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alashkin/subscriptions","organizations_url":"https://api.github.com/users/alashkin/orgs","repos_url":"https://api.github.com/users/alashkin/repos","events_url":"https://api.github.com/users/alashkin/events{/privacy}","received_events_url":"https://api.github.com/users/alashkin/received_events","type":"User","site_admin":false},"body":"Date class is implemented in this pull request. Should close #132\r\n\r\nRebased source edition.\r\nMarco's comments from #258 is incorporated.","created_at":"2015-02-16T17:26:07Z","updated_at":"2015-02-18T18:34:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9dccc98b6672e0ff0ff94df6eefb3e703a4b2e44","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cesanta/v7/pulls/260/commits","review_comments_url":"https://api.github.com/repos/cesanta/v7/pulls/260/comments","review_comment_url":"https://api.github.com/repos/cesanta/v7/pulls/comments/{number}","comments_url":"https://api.github.com/repos/cesanta/v7/issues/260/comments","statuses_url":"https://api.github.com/repos/cesanta/v7/statuses/ec6f400a91fc5432dab30527e0839c02281262cd","head":{"label":"alashkin:master","ref":"master","sha":"ec6f400a91fc5432dab30527e0839c02281262cd","user":{"login":"alashkin","id":5459304,"avatar_url":"https://avatars.githubusercontent.com/u/5459304?v=3","gravatar_id":"","url":"https://api.github.com/users/alashkin","html_url":"https://github.com/alashkin","followers_url":"https://api.github.com/users/alashkin/followers","following_url":"https://api.github.com/users/alashkin/following{/other_user}","gists_url":"https://api.github.com/users/alashkin/gists{/gist_id}","starred_url":"https://api.github.com/users/alashkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alashkin/subscriptions","organizations_url":"https://api.github.com/users/alashkin/orgs","repos_url":"https://api.github.com/users/alashkin/repos","events_url":"https://api.github.com/users/alashkin/events{/privacy}","received_events_url":"https://api.github.com/users/alashkin/received_events","type":"User","site_admin":false},"repo":{"id":30587362,"name":"v7","full_name":"alashkin/v7","owner":{"login":"alashkin","id":5459304,"avatar_url":"https://avatars.githubusercontent.com/u/5459304?v=3","gravatar_id":"","url":"https://api.github.com/users/alashkin","html_url":"https://github.com/alashkin","followers_url":"https://api.github.com/users/alashkin/followers","following_url":"https://api.github.com/users/alashkin/following{/other_user}","gists_url":"https://api.github.com/users/alashkin/gists{/gist_id}","starred_url":"https://api.github.com/users/alashkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alashkin/subscriptions","organizations_url":"https://api.github.com/users/alashkin/orgs","repos_url":"https://api.github.com/users/alashkin/repos","events_url":"https://api.github.com/users/alashkin/events{/privacy}","received_events_url":"https://api.github.com/users/alashkin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/alashkin/v7","description":"Embedded JavaScript engine for C/C++","fork":true,"url":"https://api.github.com/repos/alashkin/v7","forks_url":"https://api.github.com/repos/alashkin/v7/forks","keys_url":"https://api.github.com/repos/alashkin/v7/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alashkin/v7/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alashkin/v7/teams","hooks_url":"https://api.github.com/repos/alashkin/v7/hooks","issue_events_url":"https://api.github.com/repos/alashkin/v7/issues/events{/number}","events_url":"https://api.github.com/repos/alashkin/v7/events","assignees_url":"https://api.github.com/repos/alashkin/v7/assignees{/user}","branches_url":"https://api.github.com/repos/alashkin/v7/branches{/branch}","tags_url":"https://api.github.com/repos/alashkin/v7/tags","blobs_url":"https://api.github.com/repos/alashkin/v7/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alashkin/v7/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alashkin/v7/git/refs{/sha}","trees_url":"https://api.github.com/repos/alashkin/v7/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alashkin/v7/statuses/{sha}","languages_url":"https://api.github.com/repos/alashkin/v7/languages","stargazers_url":"https://api.github.com/repos/alashkin/v7/stargazers","contributors_url":"https://api.github.com/repos/alashkin/v7/contributors","subscribers_url":"https://api.github.com/repos/alashkin/v7/subscribers","subscription_url":"https://api.github.com/repos/alashkin/v7/subscription","commits_url":"https://api.github.com/repos/alashkin/v7/commits{/sha}","git_commits_url":"https://api.github.com/repos/alashkin/v7/git/commits{/sha}","comments_url":"https://api.github.com/repos/alashkin/v7/comments{/number}","issue_comment_url":"https://api.github.com/repos/alashkin/v7/issues/comments/{number}","contents_url":"https://api.github.com/repos/alashkin/v7/contents/{+path}","compare_url":"https://api.github.com/repos/alashkin/v7/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alashkin/v7/merges","archive_url":"https://api.github.com/repos/alashkin/v7/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alashkin/v7/downloads","issues_url":"https://api.github.com/repos/alashkin/v7/issues{/number}","pulls_url":"https://api.github.com/repos/alashkin/v7/pulls{/number}","milestones_url":"https://api.github.com/repos/alashkin/v7/milestones{/number}","notifications_url":"https://api.github.com/repos/alashkin/v7/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alashkin/v7/labels{/name}","releases_url":"https://api.github.com/repos/alashkin/v7/releases{/id}","created_at":"2015-02-10T10:37:30Z","updated_at":"2015-02-18T17:00:15Z","pushed_at":"2015-02-18T17:03:37Z","git_url":"git://github.com/alashkin/v7.git","ssh_url":"git@github.com:alashkin/v7.git","clone_url":"https://github.com/alashkin/v7.git","svn_url":"https://github.com/alashkin/v7","homepage":"","size":6581,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cesanta:master","ref":"master","sha":"d1906680be7bbfe659ec225800541c659c6f1227","user":{"login":"cesanta","id":5111322,"avatar_url":"https://avatars.githubusercontent.com/u/5111322?v=3","gravatar_id":"","url":"https://api.github.com/users/cesanta","html_url":"https://github.com/cesanta","followers_url":"https://api.github.com/users/cesanta/followers","following_url":"https://api.github.com/users/cesanta/following{/other_user}","gists_url":"https://api.github.com/users/cesanta/gists{/gist_id}","starred_url":"https://api.github.com/users/cesanta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cesanta/subscriptions","organizations_url":"https://api.github.com/users/cesanta/orgs","repos_url":"https://api.github.com/users/cesanta/repos","events_url":"https://api.github.com/users/cesanta/events{/privacy}","received_events_url":"https://api.github.com/users/cesanta/received_events","type":"Organization","site_admin":false},"repo":{"id":15176507,"name":"v7","full_name":"cesanta/v7","owner":{"login":"cesanta","id":5111322,"avatar_url":"https://avatars.githubusercontent.com/u/5111322?v=3","gravatar_id":"","url":"https://api.github.com/users/cesanta","html_url":"https://github.com/cesanta","followers_url":"https://api.github.com/users/cesanta/followers","following_url":"https://api.github.com/users/cesanta/following{/other_user}","gists_url":"https://api.github.com/users/cesanta/gists{/gist_id}","starred_url":"https://api.github.com/users/cesanta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cesanta/subscriptions","organizations_url":"https://api.github.com/users/cesanta/orgs","repos_url":"https://api.github.com/users/cesanta/repos","events_url":"https://api.github.com/users/cesanta/events{/privacy}","received_events_url":"https://api.github.com/users/cesanta/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cesanta/v7","description":"Embedded JavaScript engine for C/C++","fork":false,"url":"https://api.github.com/repos/cesanta/v7","forks_url":"https://api.github.com/repos/cesanta/v7/forks","keys_url":"https://api.github.com/repos/cesanta/v7/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cesanta/v7/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cesanta/v7/teams","hooks_url":"https://api.github.com/repos/cesanta/v7/hooks","issue_events_url":"https://api.github.com/repos/cesanta/v7/issues/events{/number}","events_url":"https://api.github.com/repos/cesanta/v7/events","assignees_url":"https://api.github.com/repos/cesanta/v7/assignees{/user}","branches_url":"https://api.github.com/repos/cesanta/v7/branches{/branch}","tags_url":"https://api.github.com/repos/cesanta/v7/tags","blobs_url":"https://api.github.com/repos/cesanta/v7/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cesanta/v7/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cesanta/v7/git/refs{/sha}","trees_url":"https://api.github.com/repos/cesanta/v7/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cesanta/v7/statuses/{sha}","languages_url":"https://api.github.com/repos/cesanta/v7/languages","stargazers_url":"https://api.github.com/repos/cesanta/v7/stargazers","contributors_url":"https://api.github.com/repos/cesanta/v7/contributors","subscribers_url":"https://api.github.com/repos/cesanta/v7/subscribers","subscription_url":"https://api.github.com/repos/cesanta/v7/subscription","commits_url":"https://api.github.com/repos/cesanta/v7/commits{/sha}","git_commits_url":"https://api.github.com/repos/cesanta/v7/git/commits{/sha}","comments_url":"https://api.github.com/repos/cesanta/v7/comments{/number}","issue_comment_url":"https://api.github.com/repos/cesanta/v7/issues/comments/{number}","contents_url":"https://api.github.com/repos/cesanta/v7/contents/{+path}","compare_url":"https://api.github.com/repos/cesanta/v7/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cesanta/v7/merges","archive_url":"https://api.github.com/repos/cesanta/v7/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cesanta/v7/downloads","issues_url":"https://api.github.com/repos/cesanta/v7/issues{/number}","pulls_url":"https://api.github.com/repos/cesanta/v7/pulls{/number}","milestones_url":"https://api.github.com/repos/cesanta/v7/milestones{/number}","notifications_url":"https://api.github.com/repos/cesanta/v7/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cesanta/v7/labels{/name}","releases_url":"https://api.github.com/repos/cesanta/v7/releases{/id}","created_at":"2013-12-13T23:28:04Z","updated_at":"2015-02-18T13:39:03Z","pushed_at":"2015-02-18T17:34:01Z","git_url":"git://github.com/cesanta/v7.git","ssh_url":"git@github.com:cesanta/v7.git","clone_url":"https://github.com/cesanta/v7.git","svn_url":"https://github.com/cesanta/v7","homepage":"","size":14253,"stargazers_count":58,"watchers_count":58,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":15,"mirror_url":null,"open_issues_count":25,"forks":15,"open_issues":25,"watchers":58,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cesanta/v7/pulls/260"},"html":{"href":"https://github.com/cesanta/v7/pull/260"},"issue":{"href":"https://api.github.com/repos/cesanta/v7/issues/260"},"comments":{"href":"https://api.github.com/repos/cesanta/v7/issues/260/comments"},"review_comments":{"href":"https://api.github.com/repos/cesanta/v7/pulls/260/comments"},"review_comment":{"href":"https://api.github.com/repos/cesanta/v7/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/cesanta/v7/pulls/260/commits"},"statuses":{"href":"https://api.github.com/repos/cesanta/v7/statuses/ec6f400a91fc5432dab30527e0839c02281262cd"}}}}