@@ -461,25 +461,30 @@ defmodule Calendar do
461461 it can't contain the `%X` format and defaults to `"%H:%M:%S"`
462462 if the option is not received
463463
464- * `:am_pm_names` - a function that receives either `:am` or `:pm` and returns
464+ * `:am_pm_names` - a function that receives either `:am` or `:pm`
465+ (and also the datetime if the function is arity/2) and returns
465466 the name of the period of the day, if the option is not received it defaults
466467 to a function that returns `"am"` and `"pm"`, respectively
467468
468- * `:month_names` - a function that receives a number and returns the name of
469+ * `:month_names` - a function that receives a number (and also the
470+ datetime if the function is arity/2) and returns the name of
469471 the corresponding month, if the option is not received it defaults to a
470472 function that returns the month names in English
471473
472- * `:abbreviated_month_names` - a function that receives a number and returns the
474+ * `:abbreviated_month_names` - a function that receives a number (and also
475+ the datetime if the function is arity/2) and returns the
473476 abbreviated name of the corresponding month, if the option is not received it
474477 defaults to a function that returns the abbreviated month names in English
475478
476- * `:day_of_week_names` - a function that receives a number and returns the name of
479+ * `:day_of_week_names` - a function that receives a number and (and also the
480+ datetime if the function is arity/2) returns the name of
477481 the corresponding day of week, if the option is not received it defaults to a
478482 function that returns the day of week names in English
479483
480- * `:abbreviated_day_of_week_names` - a function that receives a number and returns
481- the abbreviated name of the corresponding day of week, if the option is not received
482- it defaults to a function that returns the abbreviated day of week names in English
484+ * `:abbreviated_day_of_week_names` - a function that receives a number (and also
485+ the datetime if the function is arity/2) and returns the abbreviated name of
486+ the corresponding day of week, if the option is not received it defaults to a
487+ function that returns the abbreviated day of week names in English
483488
484489 ## Formatting syntax
485490
@@ -650,12 +655,12 @@ defmodule Calendar do
650655 format_modifiers ( rest , width , pad , datetime , format_options , acc )
651656 end
652657
653- defp am_pm ( hour , format_options ) when hour > 11 do
654- format_options . am_pm_names . ( :pm )
658+ defp am_pm ( hour , format_options , datetime ) when hour > 11 do
659+ apply_format ( :pm , format_options . am_pm_names , datetime )
655660 end
656661
657- defp am_pm ( hour , format_options ) when hour <= 11 do
658- format_options . am_pm_names . ( :am )
662+ defp am_pm ( hour , format_options , datetime ) when hour <= 11 do
663+ apply_format ( :am , format_options . am_pm_names , datetime )
659664 end
660665
661666 defp default_pad ( format ) when format in ~c" aAbBpPZ" , do: ?\s
@@ -676,7 +681,7 @@ defmodule Calendar do
676681 result =
677682 datetime
678683 |> Date . day_of_week ( )
679- |> format_options . abbreviated_day_of_week_names . ( )
684+ |> apply_format ( format_options . abbreviated_day_of_week_names , datetime )
680685 |> pad_leading ( width , pad )
681686
682687 parse ( rest , datetime , format_options , [ result | acc ] )
@@ -687,7 +692,7 @@ defmodule Calendar do
687692 result =
688693 datetime
689694 |> Date . day_of_week ( )
690- |> format_options . day_of_week_names . ( )
695+ |> apply_format ( format_options . day_of_week_names , datetime )
691696 |> pad_leading ( width , pad )
692697
693698 parse ( rest , datetime , format_options , [ result | acc ] )
@@ -697,15 +702,18 @@ defmodule Calendar do
697702 defp format_modifiers ( "b" <> rest , width , pad , datetime , format_options , acc ) do
698703 result =
699704 datetime . month
700- |> format_options . abbreviated_month_names . ( )
705+ |> apply_format ( format_options . abbreviated_month_names , datetime )
701706 |> pad_leading ( width , pad )
702707
703708 parse ( rest , datetime , format_options , [ result | acc ] )
704709 end
705710
706711 # Full month name
707712 defp format_modifiers ( "B" <> rest , width , pad , datetime , format_options , acc ) do
708- result = datetime . month |> format_options . month_names . ( ) |> pad_leading ( width , pad )
713+ result =
714+ datetime . month
715+ |> apply_format ( format_options . month_names , datetime )
716+ |> pad_leading ( width , pad )
709717
710718 parse ( rest , datetime , format_options , [ result | acc ] )
711719 end
@@ -783,7 +791,11 @@ defmodule Calendar do
783791
784792 # "AM" or "PM" (noon is "PM", midnight as "AM")
785793 defp format_modifiers ( "p" <> rest , width , pad , datetime , format_options , acc ) do
786- result = datetime . hour |> am_pm ( format_options ) |> String . upcase ( ) |> pad_leading ( width , pad )
794+ result =
795+ datetime . hour
796+ |> am_pm ( format_options , datetime )
797+ |> String . upcase ( )
798+ |> pad_leading ( width , pad )
787799
788800 parse ( rest , datetime , format_options , [ result | acc ] )
789801 end
@@ -792,7 +804,7 @@ defmodule Calendar do
792804 defp format_modifiers ( "P" <> rest , width , pad , datetime , format_options , acc ) do
793805 result =
794806 datetime . hour
795- |> am_pm ( format_options )
807+ |> am_pm ( format_options , datetime )
796808 |> String . downcase ( )
797809 |> pad_leading ( width , pad )
798810
@@ -958,6 +970,18 @@ defmodule Calendar do
958970 defp do_pad_leading ( count , padding , acc ) ,
959971 do: do_pad_leading ( count - 1 , padding , [ padding | acc ] )
960972
973+ defp apply_format ( term , formatter , _datetime ) when is_function ( formatter , 1 ) do
974+ formatter . ( term )
975+ end
976+
977+ defp apply_format ( term , formatter , datetime ) when is_function ( formatter , 2 ) do
978+ formatter . ( term , datetime )
979+ end
980+
981+ defp apply_format ( _term , formatter , _datetime ) do
982+ raise ArgumentError , "formatter functions must be of arity 1 or 2, got: #{ inspect ( formatter ) } "
983+ end
984+
961985 defp options ( user_options ) do
962986 default_options = % {
963987 preferred_date: "%Y-%m-%d" ,
0 commit comments