博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
erlang国际化时间转换(ISO 8601)
阅读量:7029 次
发布时间:2019-06-28

本文共 10919 字,大约阅读时间需要 36 分钟。

hot3.png

** 什么是ISO 8601**

国际标准化组织的国际标准ISO 8601是日期和时间表示方法,全称为<<数据存储和交互形式 信息交换 日期和时间的表示方法>>。目前最新为第三版ISO8601:2004, 第一版为ISO8601:1988, 第二版为ISO8601:2000。

日期和时间的组合表示法

合并表示时,要在时间前面加一大写字母T, 如要表示北京时间2004年5月3日下午5点30分8秒,可以写成2004-05-03T17:30:08+08:00或20040503T173008+08。

详细内容请查阅百度百科

输入图片说明

erlang时间与日期处理

** iso8601库**

下面把德国时间转换为北京时间

输入图片说明

世界各国时间转换网址:

使用iso8601库进行转换结果: 输入图片说明

代码如下:

-module(iso8601).-export([add_time/4,         format/1,         parse/1,         parse_exact/1]).-export_types([timestamp/0]).-define(MIDNIGHT, {0,0,0}).-define(V, proplists:get_value).-type datetime_plist() :: list({atom(), integer()}).-type maybe(A) :: undefined | A.-type timestamp() :: {MegaSecs::integer(),                      Secs::integer(),                      MicroSecs::integer() | float()}.%% API-spec add_time (calendar:datetime(), integer(), integer(), integer())               -> calendar:datetime().%% @doc Add some time to the supplied `calendar:datetime()'.add_time(Datetime, H, M, S) ->    apply_offset(Datetime, H, M, S).-spec format (calendar:datetime() | timestamp()) -> binary().%% @doc Convert a `util:timestamp()' or a calendar-style `{date(), time()}'%% tuple to an ISO 8601 formatted string. Note that this function always%% returns a string with no offset (i.e., ending in "Z").format({_,_,_}=Timestamp) ->    format(calendar:now_to_datetime(Timestamp));format({
{Y,Mo,D}, {H,Mn,S}}) when is_float(S) -> FmtStr = "~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~9.6.0fZ", IsoStr = io_lib:format(FmtStr, [Y, Mo, D, H, Mn, S]), list_to_binary(IsoStr);format({
{Y,Mo,D}, {H,Mn,S}}) -> FmtStr = "~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ", IsoStr = io_lib:format(FmtStr, [Y, Mo, D, H, Mn, S]), list_to_binary(IsoStr).-spec parse (string()) -> calendar:datetime().%% @doc Convert an ISO 8601 formatted string to aparse(Bin) when is_binary(Bin) -> parse(binary_to_list(Bin));parse(Str) -> {
{Date, {H, M, S}}, Subsecond} = year(Str, []), {Date, {H, M, S + round(Subsecond)}}.-spec parse_exact (string()) -> calendar:datetime().%% @doc Convert an ISO 8601 formatted string to a `{date(), time()}'%% tuple with seconds precision to 3 decimal palcesparse_exact(Bin) when is_binary(Bin) -> parse_exact(binary_to_list(Bin));parse_exact(Str) -> {
{Date, {H, M, S}}, SecondsDecimal} = year(Str, []), {Date, {H, M, S + SecondsDecimal}}.%% Private functionsyear([Y1,Y2,Y3,Y4|Rest], Acc) -> acc([Y1,Y2,Y3,Y4], Rest, year, Acc, fun month_or_week/2);year(_, _) -> error(badarg).month_or_week([], Acc) -> datetime(Acc);month_or_week([$-,$W,W1,W2|Rest], Acc) -> acc([W1,W2], Rest, week, Acc, fun week_day/2);month_or_week([$-,D1,D2,D3], Acc) -> %% ordinal date, no time io:format("Ordinal date, no time!~n"), acc_ordinal_date(D1, D2, D3, [], Acc, fun hour/2);month_or_week([$-,D1,D2,D3,$T|Rest], Acc) -> %% ordinal date with time io:format("Ordinal date, time is ~p!~n", [Rest]), acc_ordinal_date(D1, D2, D3, [$T|Rest], Acc, fun hour/2);month_or_week([$-,M1,M2|Rest], Acc) -> acc([M1,M2], Rest, month, Acc, fun month_day/2);month_or_week([$W,W1,W2|Rest], Acc) -> acc([W1,W2], Rest, week, Acc, fun week_day_no_hyphen/2);month_or_week([M1,M2|Rest], Acc) -> acc([M1,M2], Rest, month, Acc, fun month_day_no_hyphen/2);month_or_week(_, _) -> error(badarg).week_day([], Acc) -> datetime(Acc);week_day([$-,D|Rest], Acc) -> acc([D], Rest, week_day, Acc, fun hour/2);week_day(_, _) -> error(badarg).week_day_no_hyphen([], Acc) -> datetime(Acc);week_day_no_hyphen([D|Rest], Acc) -> acc([D], Rest, week_day, Acc, fun hour/2);week_day_no_hyphen(_, _) -> error(badarg).month_day([], Acc) -> datetime(Acc);month_day([$-,D1,D2|Rest], Acc) -> acc([D1,D2], Rest, month_day, Acc, fun hour/2);month_day(_, _) -> error(badarg).month_day_no_hyphen([], _) -> error(badarg); % omission of day disallowed by spec in this casemonth_day_no_hyphen([D1,D2|Rest], Acc) -> acc([D1,D2], Rest, month_day, Acc, fun hour/2);month_day_no_hyphen(_, _) -> error(badarg).hour([], Acc) -> datetime(Acc);hour([$T,H1,H2,$.|Rest], Acc) -> acc([H1,H2], Rest, hour, Acc, fun hour_decimal/2);hour([$T,H1,H2,$,|Rest], Acc) -> acc([H1,H2], Rest, hour, Acc, fun hour_decimal/2);hour([$T,H1,H2|Rest], Acc) -> acc([H1,H2], Rest, hour, Acc, fun minute/2);hour(_, _) -> error(badarg).hour_decimal(Str, Acc) -> decimal(Str, Acc, hour_decimal).minute([], Acc) -> datetime(Acc);minute([$:,M1,M2,$.|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2);minute([$:,M1,M2,$,|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2);minute([$:,M1,M2|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun second/2);minute([M1,M2,$.|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2);minute([M1,M2,$,|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2);minute([M1,M2|Rest], Acc) -> acc([M1,M2], Rest, minute, Acc, fun second_no_colon/2);minute(_, _) -> error(badarg).minute_decimal(Str, Acc) -> decimal(Str, Acc, minute_decimal).second([], Acc) -> datetime(Acc);second([$:,S1,S2,$.|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun second_decimal/2);second([$:,S1,S2,$,|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun second_decimal/2);second([$:,S1,S2|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun offset_hour/2);second(_, _) -> error(badarg).second_no_colon([], Acc) -> datetime(Acc);second_no_colon([S1,S2,$.|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun second_decimal/2);second_no_colon([S1,S2,$,|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun second_decimal/2);second_no_colon([S1,S2|Rest], Acc) -> acc([S1,S2], Rest, second, Acc, fun offset_hour/2);second_no_colon(_, _) -> error(badarg).second_decimal(Str, Acc) -> decimal(Str, Acc, second_decimal).decimal([], _, _) -> error(badarg);decimal(Str, Acc, Key) -> F = fun(X) when is_integer(X), X >= $0, X =< $9 -> true; (_) -> false end, {Parts, Rest} = lists:splitwith(F, Str), acc_float([$0,$.|Parts], Rest, Key, Acc, fun offset_hour/2).offset_hour([], Acc) -> datetime(Acc);offset_hour([$Z], Acc) -> datetime(Acc);offset_hour([$+,H1,H2|Rest], Acc) -> acc([H1,H2], Rest, offset_hour, Acc, fun offset_minute/2);offset_hour([$-,H1,H2|Rest], Acc) -> acc([H1,H2], Rest, offset_hour, [{offset_sign, -1}|Acc], fun offset_minute/2);offset_hour(_, _) -> error(badarg).offset_minute([], Acc) -> datetime(Acc);offset_minute([$:,M1,M2], Acc) -> acc([M1,M2], [], offset_minute, Acc, fun datetime/2);offset_minute([M1,M2], Acc) -> acc([M1,M2], [], offset_minute, Acc, fun datetime/2);offset_minute(_, _) -> error(badarg).acc(IntStr, Rest, Key, Acc, NextF) -> Acc1 = [{Key, list_to_integer(IntStr)}|Acc], NextF(Rest, Acc1).acc_float(FloatStr, Rest, Key, Acc, NextF) -> Acc1 = [{Key, list_to_float(FloatStr)}|Acc], NextF(Rest, Acc1).acc_ordinal_date(D1, D2, D3, Rest, Acc, NextF) -> Days = list_to_integer([D1, D2, D3]), Days > 0 orelse error(badarg), Year = ?V(year, Acc), Year =/= undefined orelse error(badarg), DaysInMonths = days_in_months_for_year(Year), { Month, Day } = unpack_ordinal_date(Days, DaysInMonths), Acc1 = [{ month, Month }, { month_day, Day }|Acc], NextF(Rest, Acc1).unpack_ordinal_date(Days, DaysInMonths) -> unpack_ordinal_date(1, Days, DaysInMonths).unpack_ordinal_date(_Month, _Days, []) -> error(badarg), { 0, 0 };unpack_ordinal_date(_Month, Days, _DaysInMonths) when Days < 0 -> error(badarg), { 0, 0 };unpack_ordinal_date(Month, Days, [DaysThisMonth|DaysInMonths]) -> case Days > DaysThisMonth of true -> unpack_ordinal_date(Month + 1, Days - DaysThisMonth, DaysInMonths); _ -> { Month, Days } end.days_in_months_for_year(Year) -> case is_leap_year(Year) of true -> [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; false -> [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] end.is_leap_year(Year) -> case Year rem 100 of 0 -> Year rem 400 =:= 0; _ -> Year rem 4 =:= 0 end.add_decimal(Datetime, Plist) -> HDecimal = ?V(hour_decimal, Plist, 0.0), MDecimal = ?V(minute_decimal, Plist, 0.0), apply_offset(Datetime, HDecimal, MDecimal, 0.0).datetime(Plist) -> {Date, WeekOffsetH} = make_date(Plist), Time = {?V(hour, Plist, 0), ?V(minute, Plist, 0), ?V(second, Plist, 0)}, Datetime = add_decimal({Date, Time}, Plist), OffsetSign = ?V(offset_sign, Plist, 1), OffsetH = -1 * OffsetSign * ?V(offset_hour, Plist, 0), OffsetM = -1 * OffsetSign * ?V(offset_minute, Plist, 0), { apply_offset(Datetime, WeekOffsetH+OffsetH, OffsetM, 0), ?V(second_decimal, Plist, 0.0) }.datetime(_, Plist) -> datetime(Plist).-spec make_date (datetime_plist()) -> {Date::calendar:date(), WeekOffsetH::non_neg_integer()}.%% @doc Return a `tuple' containing a date and, if the date is in week format,%% an offset in hours that can be applied to the date to adjust it to midnight%% of the day specified. If month format is used, the offset will be zero.make_date(Plist) -> Year = ?V(year, Plist), Year =/= undefined orelse error(badarg), make_date(Year, ?V(month, Plist, 1), ?V(week, Plist), Plist).-spec make_date (non_neg_integer(), maybe(pos_integer()), maybe(pos_integer()), datetime_plist()) -> {calendar:date(), non_neg_integer()}.%% @doc Return a `tuple' containing a date and - if the date is in week format%% (i.e., `Month' is undefined, `Week' is not) - an offset in hours that can be%% applied to the date to adjust it to midnight of the day specified. If month%% format is used (i.e., `Week' is undefined, `Month' is not), the offset will%% be zero.make_date(Year, Month, undefined, Plist) -> Date = {Year, Month, ?V(month_day, Plist, 1)}, {Date, 0};make_date(Year, _, Week, Plist) -> Weekday = ?V(week_day, Plist, 1), OffsetH = ((Week-1)*7 + (Weekday-1))*24, % week/weekday offset in hours {date_at_w01_1(Year), OffsetH}.-spec date_at_w01_1(pos_integer()) -> calendar:date().%% @doc Calculate the `calendar:date()' at ISO week 1, day 1 in the supplied%% year.date_at_w01_1(Year) -> case calendar:day_of_the_week({Year,1,1}) of 1 -> {Year, 1, 1}; 2 -> {Year-1, 12, 31}; 3 -> {Year-1, 12, 30}; 4 -> {Year-1, 12, 29}; 5 -> {Year, 1, 4}; 6 -> {Year, 1, 3}; 7 -> {Year, 1, 2} end.-spec apply_offset (calendar:datetime(), number(), number(), number()) -> calendar:datetime().%% @doc Add the specified number of hours, minutes and seconds to `Datetime'.apply_offset(Datetime, H, M, S) -> OffsetS = S + (60 * (M + (60 * H))), Gs = round(OffsetS) + calendar:datetime_to_gregorian_seconds(Datetime), calendar:gregorian_seconds_to_datetime(Gs).

转载于:https://my.oschina.net/lvhuizhenblog/blog/790278

你可能感兴趣的文章
Intellij修改模板代码
查看>>
2.页面布局示例笔记
查看>>
一些老游戏CPU 100%占用的解决方法
查看>>
f5基本介绍
查看>>
博前语
查看>>
Java SE核心之一:常用类,包装类,其他基本数据类型包装类。
查看>>
郑捷《机器学习算法原理与编程实践》学习笔记(第二章 中文文本分类(一))...
查看>>
python (ploit)
查看>>
Android 用achartengine 画折线图怎么显示不正确
查看>>
程序简单的测试与升级(暨实践第一次作业)
查看>>
信号处理
查看>>
【100题】第五十九题 用C++编写不能被继承的类
查看>>
轻描淡写
查看>>
mysql基本操作
查看>>
39.CSS3弹性伸缩布局【下】
查看>>
[javascript]图解+注释版 Ext.extend()
查看>>
我的前端工具集(七)div背景网格
查看>>
linux 下mongo 基础配置
查看>>
【Dubbo实战】 Dubbo+Zookeeper+Spring整合应用篇-Dubbo基于Zookeeper实现分布式服务(转)...
查看>>
JUnit单元测试中的setUpBeforeClass()、tearDownAfterClass()、setUp()、tearDown()方法小结
查看>>