Current section

Files

Jump to
ecrontab src ecrontab_next_time.erl
Raw

src/ecrontab_next_time.erl

-module(ecrontab_next_time).
-include("ecrontab_parse.hrl").
-export([
next_timestamp/1, next_timestamp/2, next_timestamp/3,
next_seconds/1, next_seconds/2, next_seconds/3,
next_datetime/1, next_datetime/2, next_datetime/3,
next_time/1, next_time/2, next_time/3
]).
%% ====================================================================
%% API
%% ====================================================================
next_timestamp(Spec) ->
next_timestamp(Spec, erlang:localtime()).
next_timestamp(Spec, NowDatetime) ->
next_timestamp(Spec, NowDatetime, []).
next_timestamp(Spec, NowDatetime, _Options) ->
case next_time_do(Spec, NowDatetime) of
{ok, Datetime} ->
{ok, ecrontab_time_util:datetime_to_timestamp(Datetime)};
Err ->
Err
end.
next_seconds(Spec) ->
next_seconds(Spec, erlang:localtime()).
next_seconds(Spec, NowDatetime) ->
next_seconds(Spec, NowDatetime, []).
next_seconds(Spec, NowDatetime, _Options) ->
case next_time_do(Spec, NowDatetime) of
{ok, Datetime} ->
{ok, calendar:datetime_to_gregorian_seconds(Datetime)};
Err ->
Err
end.
next_datetime(Spec) ->
next_datetime(Spec, erlang:localtime()).
next_datetime(Spec, NowDatetime) ->
next_datetime(Spec, NowDatetime, []).
next_datetime(Spec, NowDatetime, _Options) ->
next_time_do(Spec, NowDatetime).
%% ====================================================================
%% next_time
%% ====================================================================
next_time(Spec) ->
next_time(Spec, erlang:localtime(), []).
-spec next_time(Spec :: spec(), NowDatetime :: calendar:datetime()) ->
{ok, NextTime :: non_neg_integer() | calendar:datetime() | non_neg_integer()}
| {false, time_over}.
next_time(Spec, NowDatetime) ->
next_time(Spec, NowDatetime, []).
next_time(Spec, NowDatetime, Options) ->
case next_time_do(Spec, NowDatetime) of
{ok, NextDatetime} = Result ->
case proplists:get_value(return , Options) of
datetime ->
Result;
timestamp ->
{ok, ecrontab_time_util:datetime_to_timestamp(NextDatetime)};
seconds ->
{ok, calendar:datetime_to_gregorian_seconds(NextDatetime)};
_ ->
Result
end;
Err ->
Err
end.
next_time_do(#spec{type = ?SPEC_TYPE_INTERVAL_YEAR, year = #spec_field{type = ?SPEC_FIELD_TYPE_INTERVAL,value = Interval}} = Spec,
NowDatetime) ->
{{LastYear,_,_},_} = NowDatetime,
NextYear = LastYear+Interval,
SpecField = #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = NextYear},
NewSpec = ecrontab_parse:get_spec_type(Spec#spec{year = SpecField}),
next_time_do(NewSpec, NowDatetime);
next_time_do(#spec{type=?SPEC_TYPE_EVERY_SECOND}, NowDatetime) ->
{ok, ecrontab_time_util:next_second(NowDatetime)};
next_time_do(#spec{type=?SPEC_TYPE_SECONDS,value=Seconds}, NowDatetime) ->
Datetime = calendar:gregorian_seconds_to_datetime(Seconds),
if
Datetime > NowDatetime ->
{ok, Datetime};
true ->
{false, time_over}
end;
next_time_do(#spec{type=?SPEC_TYPE_ONLY_ONE,value=N}=Spec, NowDatetime) ->
next_time_only_one(N, Spec, NowDatetime);
next_time_do(Spec, NowDatetime) ->
#spec{year = Year, month = Month, day = Day, week = Week,
hour = Hour, minute = Minute, second = Second} = Spec,
next_time_year(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime).
%% ====================================================================
%% next_time_year
%% ====================================================================
next_time_year(#spec_field{type = ?SPEC_FIELD_TYPE_ANY}, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
NowYear = ecrontab_time_util:get_datetime_year(NowDatetime),
next_time_year_any(NowYear, Month, Day, Week, Hour, Minute, Second, NowDatetime);
next_time_year(#spec_field{type = ?SPEC_FIELD_TYPE_NUM, value = Year}, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
NowYear = ecrontab_time_util:get_datetime_year(NowDatetime),
if
Year < NowYear ->
{false, time_over};
true ->
case next_time_month(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
{false, time_over};
Result ->
Result
end
end;
next_time_year(#spec_field{type = ?SPEC_FIELD_TYPE_LIST, value = List}, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
NowYear = ecrontab_time_util:get_datetime_year(NowDatetime),
case ordsets:is_element(NowYear, List) of
true ->
case next_time_month(NowYear, Month, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_year_list(NowYear, List, Month, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
false ->
next_time_year_list(NowYear, List, Month, Day, Week, Hour, Minute, Second, NowDatetime)
end.
next_time_year_any(NowYear, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
case next_time_month(NowYear, Month, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_year_any(NowYear+1, Month, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end.
next_time_year_list(NowYear, List, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
case find_next_in_list(NowYear, List) of
false ->
{false, time_over};
NextYear ->
case next_time_month(NextYear, Month, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_year_list(NextYear, List, Month, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end.
%% ====================================================================
%% next_time_month
%% ====================================================================
next_time_month(Year, #spec_field{type = ?SPEC_FIELD_TYPE_ANY}, Day, Week, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,NowMonth,_},_} ->
next_time_month_any(Year, NowMonth, Day, Week, Hour, Minute, Second, NowDatetime);
_ ->
next_time_month_any(Year, 1, Day, Week, Hour, Minute, Second, NowDatetime)
end;
next_time_month(Year, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Month}, Day, Week, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,NowMonth,_},_} when NowMonth < Month ->
false;
_ ->
next_time_day_or_week(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime)
end;
next_time_month(Year, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, Day, Week, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,NowMonth,_},_} ->
case ordsets:is_element(NowMonth, List) of
true ->
case next_time_day_or_week(Year, NowMonth, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_month_list(Year, NowMonth, List, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
false ->
next_time_month_list(Year, NowMonth, List, Day, Week, Hour, Minute, Second, NowDatetime)
end;
_ ->
NextMonth = hd(List),
case next_time_day_or_week(Year, NextMonth, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_month_list(Year, NextMonth, List, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end.
next_time_month_any(Year, NowMonth, Day, Week, Hour, Minute, Second, NowDatetime) ->
case next_time_day_or_week(Year, NowMonth, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
case NowMonth of
12 ->
false;
_ ->
next_time_month_any(Year, NowMonth+1, Day, Week, Hour, Minute, Second, NowDatetime)
end;
Result ->
Result
end.
next_time_month_list(Year, NowMonth, List, Day, Week, Hour, Minute, Second, NowDatetime) ->
case find_next_in_list(NowMonth, List) of
false ->
false;
NextMonth ->
case next_time_day_or_week(Year, NextMonth, Day, Week, Hour, Minute, Second, NowDatetime) of
false ->
next_time_month_list(Year, NextMonth, List, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end.
%% ====================================================================
%% next_time_day_or_week
%% ====================================================================
next_time_day_or_week(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
case {Day#spec_field.type, Week#spec_field.type} of
{_, ?SPEC_FIELD_TYPE_ANY} ->
next_time_day(Year, Month, Day, Hour, Minute, Second, NowDatetime);
{?SPEC_FIELD_TYPE_ANY, ?SPEC_FIELD_TYPE_ANY} ->
next_time_day(Year, Month, Day, Hour, Minute, Second, NowDatetime);
{?SPEC_FIELD_TYPE_ANY, _} ->
next_time_week(Year, Month, Week, Hour, Minute, Second, NowDatetime);
_ ->
case {next_time_day(Year, Month, Day, Hour, Minute, Second, NowDatetime),
next_time_week(Year, Month, Week, Hour, Minute, Second, NowDatetime)} of
{false, false} ->
false;
{false, Result} ->
Result;
{Result, false} ->
Result;
{{ok, Seconds1}, {ok, Seconds2}} when Seconds1 < Seconds2 ->
{ok, Seconds1};
{_, Result} ->
Result
end
end.
%% ====================================================================
%% next_time_day
%% ====================================================================
next_time_day(Year, Month, #spec_field{type = ?SPEC_FIELD_TYPE_ANY}, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,Month,NowDay},_} ->
next_time_day_any(Year, Month, NowDay, Hour, Minute, Second, NowDatetime);
_ ->
next_time_day_any(Year, Month, 1, Hour, Minute, Second, NowDatetime)
end;
next_time_day(Year, Month, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Day}, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,Month,NowDay},_} when NowDay > Day ->
false;
_ ->
LastDay = calendar:last_day_of_the_month(Year, Month),
if
Day > LastDay ->
false;
true ->
Date = {Year, Month, Day},
next_time_hour(Date, Hour, Minute, Second, NowDatetime)
end
end;
next_time_day(Year, Month, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,Month,NowDay}=NowDate,_} ->
case ordsets:is_element(NowDay, List) of
true ->
case next_time_hour(NowDate, Hour, Minute, Second, NowDatetime) of
false ->
LastDay = calendar:last_day_of_the_month(Year, Month),
next_time_day_list(Year, Month, NowDay, LastDay, List, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
false ->
LastDay = calendar:last_day_of_the_month(Year, Month),
next_time_day_list(Year, Month, NowDay, LastDay, List, Hour, Minute, Second, NowDatetime)
end;
_ ->
LastDay = calendar:last_day_of_the_month(Year, Month),
NextDay = hd(List),
if
NextDay > LastDay ->
false;
true ->
case next_time_hour({Year, Month, NextDay}, Hour, Minute, Second, NowDatetime) of
false ->
next_time_day_list(Year, Month, NextDay, LastDay, List, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end
end.
next_time_day_any(Year, Month, NowDay, Hour, Minute, Second, NowDatetime) ->
case next_time_hour({Year, Month, NowDay}, Hour, Minute, Second, NowDatetime) of
false ->
LastDay = calendar:last_day_of_the_month(Year, Month),
case NowDay of
LastDay ->
false;
_ ->
next_time_day_any_do(Year, Month, NowDay+1, LastDay, Hour, Minute, Second, NowDatetime)
end;
Result ->
Result
end.
next_time_day_any_do(Year, Month, NowDay, LastDay, Hour, Minute, Second, NowDatetime) ->
case next_time_hour({Year, Month, NowDay}, Hour, Minute, Second, NowDatetime) of
false ->
case NowDay of
LastDay ->
false;
_ ->
next_time_day_any_do(Year, Month, NowDay+1, LastDay, Hour, Minute, Second, NowDatetime)
end;
Result ->
Result
end.
next_time_day_list(Year, Month, NowDay, LastDay, List, Hour, Minute, Second, NowDatetime) ->
case find_next_in_list(NowDay, List) of
false ->
false;
NextDay when NextDay > LastDay ->
false;
NextDay ->
case next_time_hour({Year, Month, NextDay}, Hour, Minute, Second, NowDatetime) of
false ->
next_time_day_list(Year, Month, NextDay, LastDay, List, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end.
%% ====================================================================
%% next_time_week
%% ====================================================================
next_time_week(Year, Month, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Week}, Hour, Minute, Second, NowDatetime) ->
case NowDatetime of
{{Year,Month,NowDay}=NowDate,_} ->
case calendar:day_of_the_week(Year, Month, NowDay) of
Week ->
case next_time_hour(NowDate, Hour, Minute, Second, NowDatetime) of
false ->
next_time_week_num(Year, Month, NowDay, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
_ ->
next_time_week_num(Year, Month, NowDay, Week, Hour, Minute, Second, NowDatetime)
end;
_ ->
case calendar:day_of_the_week(Year, Month, 1) of
Week ->
case next_time_hour({Year, Month, 1}, Hour, Minute, Second, NowDatetime) of
false ->
next_time_week_num(Year, Month, 1, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
_ ->
next_time_week_num(Year, Month, 1, Week, Hour, Minute, Second, NowDatetime)
end
end;
next_time_week(Year, Month, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, Hour, Minute, Second, NowDatetime) ->
LastDay = calendar:last_day_of_the_month(Year, Month),
DateWeekList =
case NowDatetime of
{{Year,Month,NowDay},_} ->
Week = calendar:day_of_the_week(Year, Month, NowDay),
get_date_week_list(Year, Month, NowDay, LastDay, Week);
_ ->
Week = calendar:day_of_the_week(Year, Month, 1),
get_date_week_list(Year, Month, 1, LastDay, Week)
end,
next_time_week_list(DateWeekList, List, Hour, Minute, Second, NowDatetime).
next_time_week_num(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime) ->
case get_next_week_date(Week, Year, Month, Day) of
false ->
false;
Date ->
case next_time_hour(Date, Hour, Minute, Second, NowDatetime) of
false ->
next_time_week_num(Year, Month, Day, Week, Hour, Minute, Second, NowDatetime);
Result ->
Result
end
end.
get_date_week_list(Year, Month, LastDay, LastDay, Week) ->
[{{Year, Month, LastDay},Week}];
get_date_week_list(Year, Month, Day, LastDay, 7) ->
[{{Year, Month, Day},7}|get_date_week_list(Year, Month, Day+1, LastDay, 1)];
get_date_week_list(Year, Month, Day, LastDay, Week) ->
[{{Year, Month, Day},Week}|get_date_week_list(Year, Month, Day+1, LastDay, Week+1)].
next_time_week_list([], _, _, _, _, _) ->
false;
next_time_week_list([{Date,Week}| DateWeekList], List, Hour, Minute, Second, NowDatetime) ->
case ordsets:is_element(Week, List) of
true ->
case next_time_hour(Date, Hour, Minute, Second, NowDatetime) of
false ->
next_time_week_list(DateWeekList, List, Hour, Minute, Second, NowDatetime);
Result ->
Result
end;
false ->
next_time_week_list(DateWeekList, List, Hour, Minute, Second, NowDatetime)
end.
get_next_week_date(Week, Year, Month, Day) ->
NowWeek = calendar:day_of_the_week(Year, Month, Day),
DiffDays =
if
NowWeek == Week ->
7;
NowWeek > Week ->
7 - (NowWeek - Week);
true ->
Week - NowWeek
end,
NowDays = calendar:date_to_gregorian_days(Year, Month, Day),
NewDays = NowDays + DiffDays,
case calendar:gregorian_days_to_date(NewDays) of
{Year,Month,_} = NewDate ->
NewDate;
_ ->
false
end.
%% ====================================================================
%% next_time_hour
%% ====================================================================
next_time_hour(Date, #spec_field{type = ?SPEC_FIELD_TYPE_ANY}, Minute, Second, NowDatetime) ->
case NowDatetime of
{Date, {NowHour,_,_}} ->
next_time_hour_any(Date, NowHour, Minute, Second, NowDatetime);
_ ->
next_time_hour_any(Date, 0, Minute, Second, NowDatetime)
end;
next_time_hour(Date, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Hour}, Minute, Second, NowDatetime) ->
case NowDatetime of
{Date, {NowHour,_,_}} when NowHour > Hour ->
false;
_ ->
next_time_minute(Date, Hour, Minute, Second, NowDatetime)
end;
next_time_hour(Date, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, Minute, Second, NowDatetime) ->
case NowDatetime of
{Date,{NowHour,_,_}} ->
case ordsets:is_element(NowHour, List) of
true ->
case next_time_minute(Date, NowHour, Minute, Second, NowDatetime) of
false ->
next_time_hour_list(Date, NowHour, List, Minute, Second, NowDatetime);
Result ->
Result
end;
false ->
next_time_hour_list(Date, NowHour, List, Minute, Second, NowDatetime)
end;
_ ->
NextHour = hd(List),
case next_time_minute(Date, NextHour, Minute, Second, NowDatetime) of
false ->
next_time_hour_list(Date, NextHour, List, Minute, Second, NowDatetime);
Result ->
Result
end
end.
next_time_hour_any(Date, NowHour, Minute, Second, NowDatetime) ->
case next_time_minute(Date, NowHour, Minute, Second, NowDatetime) of
false ->
case NowHour of
23 ->
false;
_ ->
next_time_hour_any(Date, NowHour+1, Minute, Second, NowDatetime)
end;
Result ->
Result
end.
next_time_hour_list(Date, NowHour, List, Minute, Second, NowDatetime) ->
case find_next_in_list(NowHour, List) of
false ->
false;
NextHour ->
case next_time_minute(Date, NextHour, Minute, Second, NowDatetime) of
false ->
next_time_hour_list(Date, NowHour, List, Minute, Second, NowDatetime);
Result ->
Result
end
end.
%% ====================================================================
%% next_time_minute
%% ====================================================================
next_time_minute(Date, Hour, #spec_field{type = ?SPEC_FIELD_TYPE_ANY}, Second, NowDatetime) ->
case NowDatetime of
{Date,{Hour,NowMinute,_}} ->
next_time_minute_any(Date, Hour, NowMinute, Second, NowDatetime);
_ ->
next_time_minute_any(Date, Hour, 0, Second, NowDatetime)
end;
next_time_minute(Date, Hour, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Minute}, Second, NowDatetime) ->
case NowDatetime of
{Date,{Hour,NowMinute,_}} when NowMinute > Minute ->
false;
_ ->
next_time_second(Date, Hour, Minute, Second, NowDatetime)
end;
next_time_minute(Date, Hour, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, Second, NowDatetime) ->
case NowDatetime of
{Date,{Hour,NowMinute,_}} ->
case ordsets:is_element(NowMinute,List) of
true ->
case next_time_second(Date, Hour, NowMinute, Second, NowDatetime) of
false ->
next_time_minute_list(Date, Hour, NowMinute, List, Second, NowDatetime);
Result ->
Result
end;
false ->
next_time_minute_list(Date, Hour, NowMinute, List, Second, NowDatetime)
end;
_ ->
NextMinute = hd(List),
case next_time_second(Date, Hour, NextMinute, Second, NowDatetime) of
false ->
next_time_minute_list(Date, Hour, NextMinute, List, Second, NowDatetime);
Result ->
Result
end
end.
next_time_minute_any(Date, Hour, NowMinute, Second, NowDatetime) ->
case next_time_second(Date, Hour, NowMinute, Second, NowDatetime) of
false ->
case NowMinute of
59 ->
false;
_ ->
next_time_minute_any(Date, Hour, NowMinute+1, Second, NowDatetime)
end;
Result ->
Result
end.
next_time_minute_list(Date, Hour, NowMinute, List, Second, NowDatetime) ->
case find_next_in_list(NowMinute,List) of
false ->
false;
NextMinute ->
case next_time_second(Date, Hour, NextMinute, Second, NowDatetime) of
false ->
next_time_minute_list(Date, Hour, NextMinute, List, Second, NowDatetime);
Result ->
Result
end
end.
%% ====================================================================
%% next_time_second
%% ====================================================================
next_time_second(Date, Hour, Minute, #spec_field{type = ?SPEC_FIELD_TYPE_ANY}, NowDatetime) ->
case NowDatetime of
{Date,{Hour,Minute,NowSecond}} ->
next_time_second_any(Date, Hour, Minute, NowSecond, NowDatetime);
_ ->
next_time_second_any(Date, Hour, Minute, 0, NowDatetime)
end;
next_time_second(Date, Hour, Minute, #spec_field{type = ?SPEC_FIELD_TYPE_NUM,value = Second}, NowDatetime) ->
case NowDatetime of
{Date,{Hour,Minute,NowSecond}} ->
if
NowSecond >= Second ->
false;
true ->
{ok, {Date, {Hour, Minute, Second}}}
end;
_ ->
{ok, {Date, {Hour, Minute, Second}}}
end;
next_time_second(Date, Hour, Minute, #spec_field{type = ?SPEC_FIELD_TYPE_LIST,value = List}, NowDatetime) ->
case NowDatetime of
{Date,{Hour,Minute,NowSecond}} ->
next_time_second_list(Date, Hour, Minute, NowSecond, List, NowDatetime);
_ ->
NextSecond = hd(List),
Datetime = {Date, {Hour,Minute,NextSecond}},
if
Datetime > NowDatetime ->
{ok, Datetime};
true ->
next_time_second_list(Date, Hour, Minute, NextSecond, List, NowDatetime)
end
end.
next_time_second_any(Date, Hour, Minute, NowSecond, NowDatetime) ->
Datetime = {Date, {Hour,Minute,NowSecond}},
if
Datetime > NowDatetime ->
{ok, Datetime};
true ->
case NowSecond of
59 ->
false;
_ ->
next_time_second_any(Date, Hour, Minute, NowSecond+1, NowDatetime)
end
end.
next_time_second_list(Date, Hour, Minute, NowSecond, List, NowDatetime) ->
case find_next_in_list(NowSecond,List) of
false ->
false;
NextSecond ->
Datetime = {Date, {Hour,Minute,NextSecond}},
if
Datetime > NowDatetime ->
{ok, Datetime};
true ->
next_time_second_list(Date, Hour, Minute, NextSecond, List, NowDatetime)
end
end.
%% ====================================================================
%% next_time_only_one start
%% ====================================================================
next_time_only_one(#spec.year,Spec,NowDatetime) ->
SpecField = Spec#spec.year,
NowYear = ecrontab_time_util:get_datetime_year(NowDatetime),
case is_passed_spec_field(NowYear, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_year(NewDatetime) of
NowYear ->
{ok, NewDatetime};
_ ->
next_time_only_one_year(SpecField,NowDatetime)
end;
false ->
next_time_only_one_year(SpecField,NowDatetime)
end;
next_time_only_one(#spec.month,Spec,NowDatetime) ->
SpecField = Spec#spec.month,
NowMonth = ecrontab_time_util:get_datetime_month(NowDatetime),
case is_passed_spec_field(NowMonth, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_month(NewDatetime) of
NowMonth ->
{ok, NewDatetime};
_ ->
next_time_only_one_month(SpecField,NowDatetime)
end;
false ->
next_time_only_one_month(SpecField,NowDatetime)
end;
next_time_only_one(#spec.day,Spec,NowDatetime) ->
SpecField = Spec#spec.day,
NowDay = ecrontab_time_util:get_datetime_day(NowDatetime),
case is_passed_spec_field(NowDay, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_day(NewDatetime) of
NowDay ->
{ok, NewDatetime};
_ ->
next_time_only_one_day(SpecField,NowDatetime)
end;
false ->
next_time_only_one_day(SpecField,NowDatetime)
end;
next_time_only_one(#spec.week,Spec,NowDatetime) ->
NowWeek = calendar:day_of_the_week(element(1,NowDatetime)),
SpecField = Spec#spec.week,
case is_passed_spec_field(NowWeek, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_week(NewDatetime) of
NowWeek ->
{ok, NewDatetime};
_ ->
next_time_only_one_week(SpecField,NowWeek,NowDatetime)
end;
false ->
next_time_only_one_week(SpecField,NowWeek,NowDatetime)
end;
next_time_only_one(#spec.hour,Spec,NowDatetime) ->
SpecField = Spec#spec.hour,
NowHour = ecrontab_time_util:get_datetime_hour(NowDatetime),
case is_passed_spec_field(NowHour, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_hour(NewDatetime) of
NowHour ->
{ok, NewDatetime};
_ ->
next_time_only_one_hour(SpecField,NowDatetime)
end;
false ->
next_time_only_one_hour(SpecField,NowDatetime)
end;
next_time_only_one(#spec.minute,Spec,NowDatetime) ->
SpecField = Spec#spec.minute,
NowMinute = ecrontab_time_util:get_datetime_minute(NowDatetime),
case is_passed_spec_field(NowMinute, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_minute(NewDatetime) of
NowMinute ->
{ok, NewDatetime};
_ ->
next_time_only_one_minute(SpecField,NowDatetime)
end;
false ->
next_time_only_one_minute(SpecField,NowDatetime)
end;
next_time_only_one(#spec.second,Spec,NowDatetime) ->
SpecField = Spec#spec.second,
NowSecond = ecrontab_time_util:get_datetime_minute(NowDatetime),
case is_passed_spec_field(NowSecond, SpecField) of
true ->
NewDatetime = ecrontab_time_util:next_second(NowDatetime),
case ecrontab_time_util:get_datetime_second(NewDatetime) of
NowSecond ->
{ok, NewDatetime};
_ ->
next_time_only_one_second(SpecField,NowDatetime)
end;
false ->
next_time_only_one_second(SpecField,NowDatetime)
end.
next_time_only_one_year(SpecField,{{NowYear,_,_},_}) ->
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextYear = SpecField#spec_field.value,
if
NextYear > NowYear ->
{ok, {{SpecField#spec_field.value,1,1},{0,0,0}}};
true ->
{false, time_over}
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowYear,List) of
false ->
{false, time_over};
NextYear ->
{ok, {{NextYear,1,1},{0,0,0}}}
end
end.
next_time_only_one_month(SpecField,{{Y,NowMonth,_},_}) ->
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextMonth = SpecField#spec_field.value,
if
NextMonth > NowMonth ->
{ok, {{Y,NextMonth,1},{0,0,0}}};
true ->
{ok, {{Y+1,NextMonth,1},{0,0,0}}}
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowMonth,List) of
false ->
NextMonth = hd(List),
{ok, {{Y+1,NextMonth,1},{0,0,0}}};
NextMonth ->
{ok, {{Y,NextMonth,1},{0,0,0}}}
end
end.
next_time_only_one_day(SpecField,{{Y,M,NowDay},_}) ->
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextDay = SpecField#spec_field.value,
if
NextDay > NowDay ->
next_time_only_one_day_do(Y,M,NextDay,{0,0,0});
true ->
case M of
12 ->
next_time_only_one_day_do(Y+1,1,NextDay,{0,0,0});
_ ->
next_time_only_one_day_do(Y,M+1,NextDay,{0,0,0})
end
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowDay,List) of
false ->
NextDay = hd(List),
next_time_only_one_day_do(Y,M,NextDay,{0,0,0});
NextDay ->
LastDay = calendar:last_day_of_the_month(Y,M),
if
LastDay < NextDay ->
NextDay2 = hd(List),
next_time_only_one_day_do(Y,M,NextDay2,{0,0,0});
true ->
{ok, {{Y,M,NextDay},{0,0,0}}}
end
end
end.
next_time_only_one_day_do(Y,M,NextDay,Time) ->
LastDay = calendar:last_day_of_the_month(Y,M),
if
LastDay < NextDay ->
case M of
12 ->
next_time_only_one_day_do(Y+1,1,NextDay,Time);
_ ->
next_time_only_one_day_do(Y,M+1,NextDay,Time)
end;
true ->
{ok, {{Y,M,NextDay},Time}}
end.
next_time_only_one_week(SpecField,NowWeek,{Date,_}) ->
Days = calendar:date_to_gregorian_days(Date),
NewDays =
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextWeek = SpecField#spec_field.value,
if
NextWeek > NowWeek ->
Days + NextWeek - NowWeek;
true ->
Days + (7 - (NowWeek - NextWeek))
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowWeek,List) of
false ->
NextWeek = hd(List),
Days + (7 - (NowWeek - NextWeek));
NextWeek ->
Days + NextWeek - NowWeek
end
end,
NewDate = calendar:gregorian_days_to_date(NewDays),
{ok,{NewDate,{0,0,0}}}.
next_time_only_one_hour(SpecField,{Date,{NowHour,_,_}}) ->
DateTime =
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextHour = SpecField#spec_field.value,
if
NextHour > NowHour ->
{Date,{NextHour,0,0}};
true ->
ecrontab_time_util:next_day({Date,{NextHour,0,0}})
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowHour,List) of
false ->
NextHour = hd(List),
ecrontab_time_util:next_day({Date,{NextHour,0,0}});
NextHour ->
{Date,{NextHour,0,0}}
end
end,
{ok, DateTime}.
next_time_only_one_minute(SpecField,{Date,{HH,NowMinute,_}}) ->
DateTime =
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextMinute = SpecField#spec_field.value,
if
NextMinute > NowMinute ->
{Date,{HH,NextMinute,0}};
true ->
ecrontab_time_util:next_hour({Date,{HH,NextMinute,0}})
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowMinute,List) of
false ->
NextMinute = hd(List),
ecrontab_time_util:next_hour({Date,{HH,NextMinute,0}});
NextMinute ->
{Date,{HH,NextMinute,0}}
end
end,
{ok, DateTime}.
next_time_only_one_second(SpecField,{Date,{HH,MM,NowSecond}}) ->
DateTime =
case SpecField#spec_field.type of
?SPEC_FIELD_TYPE_NUM ->
NextSecond = SpecField#spec_field.value,
if
NextSecond > NowSecond ->
{Date,{HH,MM,NextSecond}};
true ->
ecrontab_time_util:next_minute({Date,{HH,MM,NextSecond}})
end;
?SPEC_FIELD_TYPE_LIST ->
List = SpecField#spec_field.value,
case find_next_in_list(NowSecond,List) of
false ->
NextSecond = hd(List),
ecrontab_time_util:next_minute({Date,{HH,MM,NextSecond}});
NextSecond ->
{Date,{HH,MM,NextSecond}}
end
end,
{ok, DateTime}.
%% ====================================================================
%% next_time_only_one end
%% ====================================================================
find_next_in_list(_,[]) ->
false;
find_next_in_list(NowValue,[Value|_]) when NowValue<Value ->
Value;
find_next_in_list(NowValue,[_|List]) ->
find_next_in_list(NowValue,List).
is_passed_spec_field(_,#spec_field{type=?SPEC_FIELD_TYPE_ANY}) ->
true;
is_passed_spec_field(Value,#spec_field{type=?SPEC_FIELD_TYPE_NUM,value=Value}) ->
true;
is_passed_spec_field(Value,#spec_field{type=?SPEC_FIELD_TYPE_LIST,value=List}) ->
ordsets:is_element(Value, List);
is_passed_spec_field(_,_) ->
false.