C库解析大致日期

我正在寻找date.js date.parse()的普通C对应物。

也就是说,将“一周前”或“昨天”理解为输入的东西。 只有英语才行。

注意:库不应该在GPL下许可,因此Git的date.c或GNU date -d解析器不会。 顺便说一句,如果你想知道为什么我不能坐下来编写代码,那么去看看提到的库的来源……

以下解决方案并不完全符合您的要求,但我希望尽管不是简单的C答案,但它可以满足您的需求。 重新发明轮子不是一种方法,所以让我们使用Mozilla JavaScript引擎SpiderMonkey运行它,在C中使用date.js。

这是我如何做到的。 我已经开始下载date.js并将其翻译成date.js.h定义的const char*命名code

 ( \ echo 'const char *code =' ; \ curl https://datejs.googlecode.com/files/date.js | \ sed -e 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/\r\?$/\\n"/'; \ echo ';' \ ) > date.js.h 

然后我拿了JSAPI的Hello,World! 作为一个起点。

 #include "jsapi.h" #include "date.js.h" static JSClass global_class = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS }; void reportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "", (unsigned int) report->lineno, message); } int main(int argc, const char *argv[]) { JSRuntime *rt; JSContext *cx; JSObject *global; rt = JS_NewRuntime(8L * 1024L * 1024L); if (rt == NULL) return 1; cx = JS_NewContext(rt, 8192); if (cx == NULL) return 1; JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL); if (global == NULL) return 1; if (!JS_InitStandardClasses(cx, global)) return 1; /* Here's where the interesting stuff is starting to take place. * Begin by evaluating sources of date.js */ jsval out; if (!JS_EvaluateScript(cx, global, code, strlen(code), "code", 1, &out)) return 1; /* Now create a call to Date.parse and evaluate it. The return value should * be a timestamp of a given date. If no errors occur convert the timestamp * to a double and print it. */ const int buflen = 1024; char parse[buflen + 1]; snprintf(parse, buflen, "Date.parse(\"%s\").getTime();", argv[1]); if (!JS_EvaluateScript(cx, global, parse, strlen(parse), "parse", 1, &out)) return 1; double val; JS_ValueToNumber(cx, out, &val); printf("%i\n", (int) (val / 1000)); /* Finally, clean everything up. */ JS_DestroyContext(cx); JS_DestroyRuntime(rt); JS_ShutDown(); return 0; } 

这是它在实践中的运作方式。

 $ time ./parse "week ago" 1331938800 0.01user 0.00system 0:00.02elapsed 92%CPU (0avgtext+0avgdata 6168maxresident)k 0inputs+0outputs (0major+1651minor)pagefaults 0swaps $ time ./parse yesterday 1332457200 0.01user 0.00system 0:00.02elapsed 84%CPU (0avgtext+0avgdata 6168maxresident)k 0inputs+0outputs (0major+1653minor)pagefaults 0swaps 

正如您所看到的那样,它非常快,您可以通过重新使用最初创建的上下文来对Date.parse所有后续调用来显着提高其性能。

说到许可问题,date.js可以根据MIT条款获得,SpiderMonkey可以在MPL 1.1,GPL 2.0或LGPL 2.1下获得。 动态链接它可以满足非GPL要求。

TL; DR: git clone https://gist.github.com/2180739.git && cd 2180739 && make && ./parse yesterday

日期格式非常可怕,没有简单的方法可以做到这一点。 您需要考虑所选语言的日期和月份名称,然后确保以特定格式接收数据:“dd / mm / yyyy”,“day mon,yyyy”等等。 此外,正如您所说,您需要解释某些特定关键字,因此您需要访问计算机上的当前时间戳(日期,时间或日期和时间)。

希望你需要Linux,我想你可以从这里开始阅读: 转换文本时间和日期信息

或者你可以简单地标记你的输入字符串,通过使用一些预定义的分隔符(逗号,斜杠,减号,空格等)将其拆分,修剪标记的空格,然后实现自动机来处理标记列表并构建日期变量。 确保为输入日期格式添加一些限制,并为错误或不兼容的标记抛出错误。