diff options
-rw-r--r-- | lib.c | 83 | ||||
-rw-r--r-- | txr.1 | 51 |
2 files changed, 117 insertions, 17 deletions
@@ -115,7 +115,7 @@ val list_f, less_f, greater_f; val prog_string; -val time_s, time_local_s, time_utc_s, time_string_s; +val time_s, time_local_s, time_utc_s, time_string_s, time_parse_s; val year_s, month_s, day_s, hour_s, min_s, sec_s, dst_s; static val env_list; @@ -9279,18 +9279,23 @@ static val broken_time_list(struct tm *tms) nao); } +static void tm_to_time_struct(val time_struct, struct tm *ptm) +{ + slotset(time_struct, year_s, num(ptm->tm_year + 1900)); + slotset(time_struct, month_s, num_fast(ptm->tm_mon + 1)); + slotset(time_struct, day_s, num_fast(ptm->tm_mday)); + slotset(time_struct, hour_s, num_fast(ptm->tm_hour)); + slotset(time_struct, min_s, num_fast(ptm->tm_min)); + slotset(time_struct, sec_s, num_fast(ptm->tm_sec)); + slotset(time_struct, dst_s, tnil(ptm->tm_isdst)); +} + static val broken_time_struct(struct tm *tms) { args_decl(args, ARGS_MIN); val ts = make_struct(time_s, nil, args); - slotset(ts, year_s, num(tms->tm_year + 1900)); - slotset(ts, month_s, num_fast(tms->tm_mon + 1)); - slotset(ts, day_s, num_fast(tms->tm_mday)); - slotset(ts, hour_s, num_fast(tms->tm_hour)); - slotset(ts, min_s, num_fast(tms->tm_min)); - slotset(ts, sec_s, num_fast(tms->tm_sec)); - slotset(ts, dst_s, tnil(tms->tm_isdst)); + tm_to_time_struct(ts, tms); return ts; } @@ -9343,12 +9348,13 @@ static void time_fields_to_tm(struct tm *ptm, val year, val month, val day, val hour, val min, val sec, val dst) { - ptm->tm_year = c_num(year) - 1900; - ptm->tm_mon = c_num(month) - 1; - ptm->tm_mday = c_num(day); - ptm->tm_hour = c_num(hour); - ptm->tm_min = c_num(min); - ptm->tm_sec = c_num(sec); + uses_or2; + ptm->tm_year = c_num(or2(year, zero)) - 1900; + ptm->tm_mon = c_num(or2(month, zero)) - 1; + ptm->tm_mday = c_num(or2(day, zero)); + ptm->tm_hour = c_num(or2(hour, zero)); + ptm->tm_min = c_num(or2(min, zero)); + ptm->tm_sec = c_num(or2(sec, zero)); if (!dst) ptm->tm_isdst = 0; @@ -9358,7 +9364,7 @@ static void time_fields_to_tm(struct tm *ptm, ptm->tm_isdst = 1; } -static void time_struct_to_tm(struct tm *ptm, val time_struct) +static void time_struct_to_tm(struct tm *ptm, val time_struct, val strict) { val year = slot(time_struct, year_s); val month = slot(time_struct, month_s); @@ -9367,6 +9373,16 @@ static void time_struct_to_tm(struct tm *ptm, val time_struct) val min = slot(time_struct, min_s); val sec = slot(time_struct, sec_s); val dst = slot(time_struct, dst_s); + + if (!strict) { + year = (year ? year : zero); + month = (month ? month : zero); + day = (day ? day : zero); + hour = (hour ? hour : zero); + min = (min ? min : zero); + sec = (sec ? sec : zero); + } + time_fields_to_tm(ptm, year, month, day, hour, min, sec, dst); } @@ -9485,7 +9501,7 @@ static val time_meth(val utc_p, val time_struct) static val time_string_meth(val time_struct, val format) { struct tm tms = { 0 }; - time_struct_to_tm(&tms, time_struct); + time_struct_to_tm(&tms, time_struct, t); char buffer[512] = ""; char *fmt = utf8_dup_to(c_str(format)); @@ -9497,6 +9513,35 @@ static val time_string_meth(val time_struct, val format) return string_own(utf8_dup_from(buffer)); } +#if HAVE_STRPTIME + +static val time_parse_meth(val time_struct, val format, val string) +{ + struct tm tms = { 0 }; + time_struct_to_tm(&tms, time_struct, nil); + val ret = nil; + + { + const wchar_t *w_str = c_str(string); + const wchar_t *w_fmt = c_str(format); + char *str = utf8_dup_to(w_str); + char *fmt = utf8_dup_to(w_fmt); + char *ptr = strptime(str, fmt, &tms); + + if (ptr != 0) { + tm_to_time_struct(time_struct, &tms); + ret = string_utf8(ptr); + } + + free(fmt); + free(str); + } + + return ret; +} + +#endif + static void time_init(void) { val time_st; @@ -9505,6 +9550,7 @@ static void time_init(void) time_local_s = intern(lit("time-local"), user_package); time_utc_s = intern(lit("time-utc"), user_package); time_string_s = intern(lit("time-string"), user_package); + time_parse_s = intern(lit("time-parse"), user_package); year_s = intern(lit("year"), user_package); month_s = intern(lit("month"), user_package); day_s = intern(lit("day"), user_package); @@ -9515,7 +9561,7 @@ static void time_init(void) time_st = make_struct_type(time_s, nil, list(time_local_s, time_utc_s, - time_string_s, nao), + time_string_s, time_parse_s, nao), list(year_s, month_s, day_s, hour_s, min_s, sec_s, dst_s, nao), nil, nil, nil, nil); @@ -9523,6 +9569,9 @@ static void time_init(void) static_slot_set(time_st, time_local_s, func_f1(nil, time_meth)); static_slot_set(time_st, time_utc_s, func_f1(t, time_meth)); static_slot_set(time_st, time_string_s, func_n2(time_string_meth)); +#if HAVE_STRPTIME + static_slot_set(time_st, time_parse_s, func_n3(time_parse_meth)); +#endif } void init(mem_t *(*oom)(mem_t *, size_t), val *stack_bottom) @@ -36601,6 +36601,57 @@ argument is a string, and follows exactly the same conventions as the format string of the C library function .codn strftime . +.coNP Method @ time-parse +.synb +.mets << time-struct .(time-parse < format << string ) +.syne +.desc +The +.code time-parse +method scans a time description in +.meta string +according to the specification given in the +.meta format +string. + +If the scan is successful, the structure +is updated with the parsed information, and +the remaining unmatched portion of +.meta string +is returned. If all of +.meta string +is matched, then an empty string is returned. +Slots of +.meta time-struct +which are originally +.code nil +are replaced with zero, even if these +zero values are not actually parsed from +.metn string . + +If the scan is unsuccessful, then +.code nil +is returned and the structure is not +altered. + +The +.meta format +argument follows the same conventions as the POSIX +C library function +.codn strptime . + +Note: the +.code time-parse +method may be unavailable if the host system does not +provide the +.code strptime +function. In this case, the +.code time-parse +static slot of the +.code time +struct is +.codn nil . + .coNP Functions @ make-time and @ make-time-utc .synb .mets (make-time < year < month < day < hour < minute < second << dst-advice ) |