From e620aaa1cf815e954fc0844cf24ecb6f87de3528 Mon Sep 17 00:00:00 2001 From: lixianjing Date: Wed, 6 Dec 2023 08:51:26 +0800 Subject: [PATCH] fscript support date_time_format --- docs/changes.md | 3 + docs/fscript_date_time.md | 35 +++++++++ src/fscript_ext/fscript_date_time.c | 26 +++++++ src/tkc/utils.c | 106 +++++++++++++++++++++++++--- src/tkc/utils.h | 43 ++++++++++- tests/fscript_date_time_test.cc | 43 +++++++++++ tests/utils_test.cc | 30 ++++++++ 7 files changed, 277 insertions(+), 9 deletions(-) create mode 100644 tests/fscript_date_time_test.cc diff --git a/docs/changes.md b/docs/changes.md index ff56e93440..2f29d0f17f 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,5 +1,8 @@ # 最新动态 +2023/12/06 + * fscript 增加 date\_time\_format + 2023/12/05 * 完善fscript部分数学函数。 * 修复上一个高亮对话框影响下一个普通窗口播放窗口动画的问题(感谢智明提供补丁) diff --git a/docs/fscript_date_time.md b/docs/fscript_date_time.md index b8f4929b7f..6aac7402e0 100644 --- a/docs/fscript_date_time.md +++ b/docs/fscript_date_time.md @@ -216,6 +216,41 @@ var dt = date_time_create(); var year = date_time_get_prop(dt, "year"); ``` +### 12.date\_time\_format + +> 格式化日期对象为字符串。 +---------------------------- + +> 格式规则: + * Y 代表年(完整显示) + * M 代表月(1-12) + * D 代表日(1-31) + * h 代表时(0-23) + * H 代表时(0-11) + * m 代表分(0-59) + * s 代表秒(0-59) + * YY 代表年(只显示末两位) + * MM 代表月(01-12) + * DD 代表日(01-31) + * hh 代表时(00-23) + * HH 代表时(00-11) + * mm 代表分(00-59) + * ss 代表秒(00-59) + +#### 原型 + +```js +date_time_format(dt, format) => str +date_time_format(epoch_time, format) => str +``` + +#### 示例 + +```js +print(date_time_format(0, "Y-M-D h:m:s")); // => "1970-1-1 0:0:0" +print(date_time_format(0, "YY-MM-DD hh:mm:ss")); // => "70-01-01 00:00:00" +``` + ### 更多示例 ```js diff --git a/src/fscript_ext/fscript_date_time.c b/src/fscript_ext/fscript_date_time.c index 5f8cf31ede..70da9b86ff 100644 --- a/src/fscript_ext/fscript_date_time.c +++ b/src/fscript_ext/fscript_date_time.c @@ -68,6 +68,31 @@ static ret_t func_date_time_set(fscript_t* fscript, fscript_args_t* args, value_ return RET_OK; } +static ret_t func_date_time_format(fscript_t* fscript, fscript_args_t* args, value_t* result) { + str_t str; + uint64_t t; + char buff[64] = {0}; + date_time_t* dt = NULL; + const char* format = NULL; + FSCRIPT_FUNC_CHECK(args->size == 2, RET_BAD_PARAMS); + + format = value_str(args->args + 1); + if (args->args[0].type == VALUE_TYPE_OBJECT) { + dt = get_date_time(fscript, args); + return_value_if_fail(dt != NULL, RET_BAD_PARAMS); + t = date_time_to_time(dt); + } else { + t = value_uint64(args->args); + } + + str_attach(&str, buff, sizeof(buff)); + tk_date_time_format(t, format, &str); + + value_dup_str(result, buff); + + return RET_OK; +} + static ret_t func_time_now_us(fscript_t* fscript, fscript_args_t* args, value_t* result) { value_set_uint64(result, time_now_us()); return RET_OK; @@ -140,6 +165,7 @@ FACTORY_TABLE_ENTRY("time_now_s", func_time_now_s) FACTORY_TABLE_ENTRY("time_now", func_time_now_s) FACTORY_TABLE_ENTRY("is_leap_year", func_year_is_leap) FACTORY_TABLE_ENTRY("get_days_of_month", func_get_days_of_month) +FACTORY_TABLE_ENTRY("date_time_format", func_date_time_format) /*主要给AWBLOCK使用*/ FACTORY_TABLE_ENTRY("date_time_set_prop", func_date_time_set_prop) diff --git a/src/tkc/utils.c b/src/tkc/utils.c index 596e65b56f..a37abcbaca 100644 --- a/src/tkc/utils.c +++ b/src/tkc/utils.c @@ -1991,14 +1991,6 @@ int tk_sscanf(const char* str, const char* format, ...) { } #endif /*HAS_NO_VSSCANF*/ -/** - * @method tk_levelize - * 将value转换成level。 - * 比如levels为"0-20;21-40;41-60;61-80;81-100",value为50,那么返回2。 - * @param {const char*} levels 级别字符串。 - * @param {int32_t} value 值。 - * @return {int32_t} 返回level。 -*/ int32_t tk_levelize(const char* levels, int32_t value) { int32_t level = 0; int32_t start = 0; @@ -2028,3 +2020,101 @@ int32_t tk_levelize(const char* levels, int32_t value) { return level; } + +#include "tkc/date_time.h" + +uint32_t tk_count_char(const char* str, char c) { + uint32_t nr = 0; + return_value_if_fail(str != NULL, 0); + + while (*str++ == c) { + nr++; + if (*str == '\0') { + break; + } + } + + return nr; +} + +ret_t tk_date_time_format(uint64_t time, const char* format, str_t* result) { + date_time_t dt; + wchar_t temp[32]; + const char* p = format; + return_value_if_fail(format != NULL && result != NULL, RET_BAD_PARAMS); + + str_clear(result); + date_time_init(&dt); + date_time_from_time(&dt, time); + memset(temp, 0x00, sizeof(temp)); + + while (*p) { + int32_t repeat = tk_count_char(p, *p); + + switch (*p) { + case 'Y': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.year % 100); + } else { + str_append_format(result, 32, "%d", dt.year); + } + break; + } + case 'M': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.month); + } else { + str_append_format(result, 32, "%d", dt.month); + } + break; + } + case 'D': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.day); + } else { + str_append_format(result, 32, "%d", dt.day); + } + break; + } + case 'h': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.hour); + } else { + str_append_format(result, 32, "%d", dt.hour); + } + break; + } + case 'H': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.hour % 12); + } else { + str_append_format(result, 32, "%d", dt.hour % 12); + } + break; + } + case 'm': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.minute); + } else { + str_append_format(result, 32, "%d", dt.minute); + } + break; + } + case 's': { + if (repeat == 2) { + str_append_format(result, 32, "%02d", dt.second); + } else { + str_append_format(result, 32, "%d", dt.second); + } + break; + } + default: { + str_append_with_len(result, p, repeat); + break; + } + } + p += repeat; + } + + return RET_OK; +} diff --git a/src/tkc/utils.h b/src/tkc/utils.h index d05db13678..723d2aee3e 100644 --- a/src/tkc/utils.h +++ b/src/tkc/utils.h @@ -1062,9 +1062,50 @@ int tk_sscanf_simple(const char* str, const char* format, ...); * @param {const char*} levels 级别字符串。 * @param {int32_t} value 值。 * @return {int32_t} 返回level。 -*/ + */ int32_t tk_levelize(const char* levels, int32_t value); +/** + * @method tk_count_char + * 统计字符串中某个字符出现的次数。 + * @param {const char*} str 字符串。 + * @param {char} c 字符。 + * @return {uint32_t} 返回字符出现的次数。 + */ +uint32_t tk_count_char(const char* str, char c); + +/** + * @method tk_date_time_format + * 格式化时间。 + * 格式规则: + * * Y 代表年(完整显示) + * * M 代表月(1-12) + * * D 代表日(1-31) + * * h 代表时(0-23) + * * H 代表时(0-11) + * * m 代表分(0-59) + * * s 代表秒(0-59) + * * YY 代表年(只显示末两位) + * * MM 代表月(01-12) + * * DD 代表日(01-31) + * * hh 代表时(00-23) + * * HH 代表时(00-11) + * * mm 代表分(00-59) + * * ss 代表秒(00-59) + * + * 如 日期时间为:2018/11/12 9:10:20 + * * "Y/M/D"显示为"2018/11/12" + * * "Y-M-D"显示为"2018-11-12" + * * "Y-M-D h:m:s"显示为"2018-11-12 9:10:20" + * * "Y-M-D hh:mm:ss"显示为"2018-11-12 09:10:20" + * + * @param {uint64_t} time 时间。 + * @param {const char*} format 格式化字符串。 + * @param {str_t*} result 用于返回结果。 + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +ret_t tk_date_time_format(uint64_t time, const char* format, str_t* result); + #define TK_STRDUP(str) ((str) != NULL) ? tk_strdup(str) : NULL #define TK_STRNDUP(str, len) ((str) != NULL) ? tk_strndup(str, len) : NULL diff --git a/tests/fscript_date_time_test.cc b/tests/fscript_date_time_test.cc new file mode 100644 index 0000000000..4e97373cd2 --- /dev/null +++ b/tests/fscript_date_time_test.cc @@ -0,0 +1,43 @@ +#include "tkc/fscript.h" +#include "tkc/object_default.h" +#include "gtest/gtest.h" + +TEST(FExpr, date_time_format1) { + value_t v; + tk_object_t* obj = object_default_create(); + + fscript_eval(obj, "date_time_format(0, \"Y\")", &v); + ASSERT_STREQ(value_str(&v), "1970"); + value_reset(&v); + + fscript_eval(obj, "date_time_format(0, \"Y-M-D\")", &v); + ASSERT_STREQ(value_str(&v), "1970-1-1"); + value_reset(&v); + + fscript_eval(obj, "date_time_format(0, \"Y-M-D h:m:s\")", &v); + ASSERT_STREQ(value_str(&v), "1970-1-1 0:0:0"); + value_reset(&v); + + TK_OBJECT_UNREF(obj); +} + + +TEST(FExpr, date_time_format2) { + value_t v; + tk_object_t* obj = object_default_create(); + + fscript_eval(obj, "var dt = date_time_create(); date_time_from_time(dt, 61); date_time_format(dt, \"Y\")", &v); + ASSERT_STREQ(value_str(&v), "1970"); + value_reset(&v); + + fscript_eval(obj, "var dt = date_time_create(); date_time_from_time(dt, 61); date_time_format(dt, \"Y-M-D\")", &v); + ASSERT_STREQ(value_str(&v), "1970-1-1"); + value_reset(&v); + + fscript_eval(obj, "var dt = date_time_create(); date_time_from_time(dt, 61); date_time_format(dt, \"Y-M-D h:m:s\")", &v); + ASSERT_STREQ(value_str(&v), "1970-1-1 0:1:1"); + value_reset(&v); + + TK_OBJECT_UNREF(obj); + +} \ No newline at end of file diff --git a/tests/utils_test.cc b/tests/utils_test.cc index e868e04026..5cb72ed750 100644 --- a/tests/utils_test.cc +++ b/tests/utils_test.cc @@ -1192,3 +1192,33 @@ TEST(Utils, levelize3) { ASSERT_EQ(tk_levelize("0-20;21-40", 30), 1); ASSERT_EQ(tk_levelize("0-20;21-40", 100), 1); } + +TEST(Utils, tk_date_time_format) { + str_t str; + char buff[128]; + + str_attach(&str, buff, sizeof(buff)); + ASSERT_EQ(tk_date_time_format(0, "", &str), RET_OK); + ASSERT_STREQ(str.str, ""); + + ASSERT_EQ(tk_date_time_format(0, "Y", &str), RET_OK); + ASSERT_STREQ(str.str, "1970"); + + ASSERT_EQ(tk_date_time_format(0, "Y-M-D", &str), RET_OK); + ASSERT_STREQ(str.str, "1970-1-1"); + + ASSERT_EQ(tk_date_time_format(0, "Y-M-D h:m:s", &str), RET_OK); + ASSERT_STREQ(str.str, "1970-1-1 0:0:0"); + + ASSERT_EQ(tk_date_time_format(0, "YY", &str), RET_OK); + ASSERT_STREQ(str.str, "70"); + + ASSERT_EQ(tk_date_time_format(0, "YY-MM-DD", &str), RET_OK); + ASSERT_STREQ(str.str, "70-01-01"); + + ASSERT_EQ(tk_date_time_format(0, "YY-MM-DD hh:mm:ss", &str), RET_OK); + ASSERT_STREQ(str.str, "70-01-01 00:00:00"); + + ASSERT_EQ(tk_date_time_format(3765, "YY-MM-DD hh:mm:ss", &str), RET_OK); + ASSERT_STREQ(str.str, "70-01-01 01:02:45"); +}