Skip to content

Instantly share code, notes, and snippets.

@sinkovsky
Created October 19, 2009 14:11
Show Gist options
  • Save sinkovsky/213407 to your computer and use it in GitHub Desktop.
Save sinkovsky/213407 to your computer and use it in GitHub Desktop.
parse_iso8601(Time) when is_list(Time) ->
parse_iso8601( list_to_binary(Time) );
parse_iso8601(Time) when is_binary(Time) ->
try
{ok, iso_to_rec(
year,
Time,
#timestamp{
year = 0,
day = 0,
month = 0,
hour = 0,
minute = 0,
second = 0,
fraction = 0,
timezone = #timezone{ hour = 0, minute = 0}
}
)
}
catch
error:_ -> {error, not_iso8601}
end.
iso_to_rec( _State, <<>>, R ) -> R;
%% these are used to come from state of parsing time seconds or
%% fraction seconds to parsing timezone
iso_to_rec(second, <<"-", Rest/bitstring>>, R) ->
iso_to_rec(tz_hour_minus, Rest, R );
iso_to_rec(fraction, <<"-", Rest/bitstring>>, R) ->
iso_to_rec(tz_hour_minus, Rest, R );
iso_to_rec(_State, <<"+", Rest/bitstring>>, R) ->
iso_to_rec(tz_hour_plus, Rest, R );
iso_to_rec(second, <<"Z", Rest/bitstring>>, R) ->
iso_to_rec(second, Rest, R);
iso_to_rec(fraction, <<"Z", Rest/bitstring>>, R) ->
iso_to_rec(second, Rest, R);
%% separator between date
iso_to_rec( State, <<"-", Rest/bitstring>>, R ) ->
iso_to_rec( State, Rest, R );
%% separators between date and time
iso_to_rec( State, <<" ", Rest/bitstring>>, R ) ->
iso_to_rec( State, Rest, R );
iso_to_rec( State, <<"T", Rest/bitstring>>, R ) ->
iso_to_rec( State, Rest, R );
%% separator between time parts
iso_to_rec( State, <<":", Rest/bitstring>>, R ) ->
iso_to_rec( State, Rest, R );
%% separators of fractional part
iso_to_rec( fraction, <<".", Rest/bitstring>>, R ) ->
iso_to_rec( fraction, Rest, R );
iso_to_rec( fraction, <<",", Rest/bitstring>>, R ) ->
iso_to_rec( fraction, Rest, R );
%% parsing date
iso_to_rec( year, <<Year:32/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( month, Rest, R#timestamp{ year = binary_to_integer(Year) } );
iso_to_rec( month, <<Month:16/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( day, Rest, R#timestamp{ month = binary_to_integer(Month) } );
iso_to_rec( day, <<Day:16/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( hour, Rest, R#timestamp{ day = binary_to_integer(Day) } );
%% parsing time
iso_to_rec( hour, <<Hour:16/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( minute, Rest, R#timestamp{ hour = binary_to_integer(Hour) } );
iso_to_rec( minute, <<Minute:16/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( second, Rest, R#timestamp{ minute = binary_to_integer(Minute) } );
iso_to_rec( second, <<Second:16/bitstring, Rest/bitstring>>, R ) ->
iso_to_rec( fraction, Rest, R#timestamp{ second = binary_to_integer(Second) } );
%% parsing fraction by character, cause we don't know its length
iso_to_rec( fraction, <<C:8/bitstring, Rest/bitstring>>, R) ->
iso_to_rec( fraction, Rest, R#timestamp{ fraction = R#timestamp.fraction * 10 + binary_to_integer(C)});
%% parsing timezone info
iso_to_rec( tz_hour_plus, <<Tz_hour:16/bitstring, Rest/bitstring>>, R) ->
iso_to_rec(tz_minute, Rest, R#timestamp{ timezone = (R#timestamp.timezone)#timezone{ hour = binary_to_integer(Tz_hour) }} );
iso_to_rec( tz_hour_minus, <<Tz_hour:16/bitstring, Rest/bitstring>>, R) ->
iso_to_rec(tz_minute, Rest, R#timestamp{ timezone = (R#timestamp.timezone)#timezone{ hour = - binary_to_integer(Tz_hour) }} );
iso_to_rec( tz_minute, <<Tz_min:16/bitstring, Rest/bitstring>>, R) ->
iso_to_rec(minute, Rest, R#timestamp{ timezone = (R#timestamp.timezone)#timezone{ minute = binary_to_integer(Tz_min) }} ).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment