diff options
Diffstat (limited to 'src/jlib.erl')
-rw-r--r-- | src/jlib.erl | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/jlib.erl b/src/jlib.erl index 07ad9333..ffd4e51d 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -37,6 +37,9 @@ parse_xdata_submit/1, timestamp_to_iso/1, timestamp_to_xml/1, + now_to_utc_string/1, + now_to_local_string/1, + datetime_string_to_timestamp/1, decode_base64/1, encode_base64/1]). @@ -438,6 +441,123 @@ timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) -> [Year, Month, Day, Hour, Minute, Second]))}], []}. +now_to_utc_string({MegaSecs, Secs, MicroSecs}) -> + {{Year, Month, Day}, {Hour, Minute, Second}} = + calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}), + lists:flatten( + io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0wZ", + [Year, Month, Day, Hour, Minute, Second, MicroSecs])). + +now_to_local_string({MegaSecs, Secs, MicroSecs}) -> + LocalTime = calendar:now_to_local_time({MegaSecs, Secs, MicroSecs}), + UTCTime = calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}), + Seconds = calendar:datetime_to_gregorian_seconds(LocalTime) - + calendar:datetime_to_gregorian_seconds(UTCTime), + {{H, M, _}, Sign} = if + Seconds < 0 -> + {calendar:seconds_to_time(-Seconds), "-"}; + true -> + {calendar:seconds_to_time(Seconds), "+"} + end, + {{Year, Month, Day}, {Hour, Minute, Second}} = LocalTime, + lists:flatten( + io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0w~s~2..0w:~2..0w", + [Year, Month, Day, Hour, Minute, Second, MicroSecs, Sign, H, M])). + + +% yyyy-mm-ddThh:mm:ss[.sss]{Z|{+|-}hh:mm} -> {MegaSecs, Secs, MicroSecs} +datetime_string_to_timestamp(TimeStr) -> + case catch parse_datetime(TimeStr) of + {'EXIT', _Err} -> + undefined; + TimeStamp -> + TimeStamp + end. + +parse_datetime(TimeStr) -> + [Date, Time] = string:tokens(TimeStr, "T"), + D = parse_date(Date), + {T, MS, TZH, TZM} = parse_time(Time), + S = calendar:datetime_to_gregorian_seconds({D, T}), + S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), + Seconds = (S - S1) - TZH * 60 * 60 - TZM * 60, + {Seconds div 1000000, Seconds rem 1000000, MS}. + +% yyyy-mm-dd +parse_date(Date) -> + [Y, M, D] = string:tokens(Date, "-"), + Date1 = {list_to_integer(Y), list_to_integer(M), list_to_integer(D)}, + case calendar:valid_date(Date1) of + true -> + Date1; + _ -> + false + end. + +% hh:mm:ss[.sss]TZD +parse_time(Time) -> + case string:str(Time, "Z") of + 0 -> + parse_time_with_timezone(Time); + _ -> + [T | _] = string:tokens(Time, "Z"), + {TT, MS} = parse_time1(T), + {TT, MS, 0, 0} + end. + +parse_time_with_timezone(Time) -> + case string:str(Time, "+") of + 0 -> + case string:str(Time, "-") of + 0 -> + false; + _ -> + parse_time_with_timezone(Time, "-") + end; + _ -> + parse_time_with_timezone(Time, "+") + end. + +parse_time_with_timezone(Time, Delim) -> + [T, TZ] = string:tokens(Time, Delim), + {TZH, TZM} = parse_timezone(TZ), + {TT, MS} = parse_time1(T), + case Delim of + "-" -> + {TT, MS, -TZH, -TZM}; + "+" -> + {TT, MS, TZH, TZM} + end. + +parse_timezone(TZ) -> + [H, M] = string:tokens(TZ, ":"), + {[H1, M1], true} = check_list([{H, 12}, {M, 60}]), + {H1, M1}. + +parse_time1(Time) -> + [HMS | T] = string:tokens(Time, "."), + MS = case T of + [] -> + 0; + [Val] -> + list_to_integer(string:left(Val, 6, $0)) + end, + [H, M, S] = string:tokens(HMS, ":"), + {[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]), + {{H1, M1, S1}, MS}. + +check_list(List) -> + lists:mapfoldl( + fun({L, N}, B)-> + V = list_to_integer(L), + if + (V >= 0) and (V =< N) -> + {V, B}; + true -> + {false, false} + end + end, true, List). + % % Base64 stuff (based on httpd_util.erl) |