C库来解析大致的日期

时间:2012-03-19 20:31:37

标签: c parsing date

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

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

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

2 个答案:

答案 0 :(得分:6)

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

我是这样做的。我已经开始下载date.js并将其翻译为const char*中定义的名为code的{​​{1}}。

date.js.h

然后我以JSAPI's Hello, World!作为起点。

( \
  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

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

#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 : "<no 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.js在MIT条款下可用,SpiderMonkey在MPL 1.1,GPL 2.0或LGPL 2.1下可用。动态链接它可以满足非GPL要求。

TL; DR: Date.parse

答案 1 :(得分:-1)

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

希望你需要Linux,我想你可以从这里开始阅读:Convert textual time and date information back

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