2012-03-19 35 views
18

Tôi đang tìm một đối tác đồng bằng C cho date.jsdate.parse().Thư viện C để phân tích cú pháp các ngày gần đúng

Tức là, cái gì đó hiểu "tuần trước" hoặc "ngày hôm qua" làm đầu vào. Tiếng Anh chỉ là OK.

Lưu ý: thư viện không được cấp phép theo GPL, do đó, date.c hoặc trình phân tích cú pháp của GNU cho GNU date -d sẽ không hoạt động. BTW, nếu bạn tự hỏi tại sao tôi không chỉ ngồi xuống và viết mã này, hãy xem nguồn thư viện được đề cập ...

+0

Đối với những gì nó có giá trị, date.js được MIT cấp phép. Vì vậy, nếu mục tiêu ở đây là để có được một cái gì đó bạn có thể liên kết với mã độc quyền, bạn nên có thể sử dụng date.js như một điểm khởi đầu an toàn nếu bạn phải cuộn của riêng bạn. Mặc dù viết lại javascript-to-C có thể không phải là một bước đi trong công viên. –

+1

Đó chính là lý do tại sao tôi hỏi câu hỏi này thay vì chỉ cần viết mã sau :-) –

+0

Nếu bạn lo lắng về sự phức tạp của nguồn để viết trình phân tích cú pháp của riêng mình, bạn có thể sử dụng các công cụ lex/yacc không? – Jerry

Trả lời

6

Giải pháp sau đây không chính xác những gì bạn đã yêu cầu nhưng tôi hy vọng rằng mặc dù không phải là câu trả lời C đơn giản, nó sẽ đáp ứng nhu cầu của bạn. Tái phát minh ra bánh xe không phải là một cách để đi vì vậy hãy sử dụng date.js trong C bằng cách chạy nó với SpiderMonkey, công cụ JavaScript của Mozilla.

Đây là cách tôi đã làm. Tôi đã bắt đầu tải xuống date.js và dịch nó thành một const char* có tên là code được xác định trong date.js.h.

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

Sau đó, tôi lấy JSAPI's Hello, World! làm điểm bắt đầu.

#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; 
} 

Đây là cách hoạt động trong thực tế.

$ 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 

Như bạn có thể thấy nó khá nhanh và bạn có thể làm tăng đáng kể hiệu quả của nó bằng cách tái sử dụng bối cảnh ban đầu được tạo ra cho tất cả các cuộc gọi tiếp theo để Date.parse.

Nói về các vấn đề cấp phép, date.js khả dụng theo các điều khoản của MIT và SpiderMonkey có sẵn theo MPL 1.1, GPL 2.0 hoặc LGPL 2.1. Việc liên kết nó tự động đáp ứng yêu cầu không phải GPL.

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

+3

Hey, lừa thông minh, cảm ơn. Tôi nghĩ rằng nó thậm chí sẽ làm việc cho trường hợp của tôi, vì tôi không cần hiệu suất cao. Tôi để lại câu hỏi mở trong trường hợp một giải pháp trung thực bật lên :-) –

-1

Định dạng ngày khá khủng khiếp, không có cách nào dễ dàng để thực hiện việc này. Bạn cần tính đến tên ngày và tháng của ngôn ngữ đã chọn, sau đó đảm bảo bạn nhận dữ liệu ở định dạng cụ thể: "dd/mm/yyyy", "ngày mon, yyyy" và cứ tiếp tục như vậy. Ngoài ra, như bạn nói, bạn cần phải diễn giải một số từ khóa cụ thể, do đó bạn cần truy cập vào dấu thời gian hiện tại (ngày, giờ hoặc ngày & thời gian) trên máy.

Hy vọng bạn cần phải có cho Linux, tôi nghĩ bạn có thể bắt đầu đọc từ đây: Convert textual time and date information back

Hoặc bạn chỉ có thể tokenize chuỗi đầu vào của bạn, bằng cách chia nó sử dụng một số dải phân cách được xác định trước (dấu phẩy, dấu gạch chéo, trừ, không gian vv .), cắt bớt các khoảng trống của các thẻ, và sau đó thực hiện một automata để xử lý danh sách các thẻ và tạo biến ngày của bạn. Đảm bảo bạn thêm một số hạn chế đối với định dạng ngày nhập và phát sai các mã thông báo sai hoặc không tương thích.

+0

Cảm ơn, nhưng 'getdate' không hiểu' ngày hôm qua' v.v ... về cách phân tích cú pháp - Tôi hiểu điều đó, nhưng câu hỏi này là về một giải pháp hiện có. Tôi ghét phải tự mình làm và đánh tất cả những cạm bẫy - việc đánh giá từ mã GPL-ed hiện tại có rất nhiều. –

Các vấn đề liên quan