@@ -1220,6 +1220,17 @@ defmodule Calendar.ISO do
12201220 :basic | :extended
12211221 ) :: String . t ( )
12221222 def time_to_string (
1223+ hour ,
1224+ minute ,
1225+ second ,
1226+ microsecond ,
1227+ format \\ :extended
1228+ ) do
1229+ time_to_iodata ( hour , minute , second , microsecond , format )
1230+ |> IO . iodata_to_binary ( )
1231+ end
1232+
1233+ def time_to_iodata (
12231234 hour ,
12241235 minute ,
12251236 second ,
@@ -1228,24 +1239,27 @@ defmodule Calendar.ISO do
12281239 )
12291240 when is_hour ( hour ) and is_minute ( minute ) and is_second ( second ) and
12301241 is_microsecond ( ms_value , ms_precision ) and format in [ :basic , :extended ] do
1231- time_to_string_guarded ( hour , minute , second , microsecond , format )
1242+ time_to_iodata_guarded ( hour , minute , second , microsecond , format )
12321243 end
12331244
1234- defp time_to_string_guarded ( hour , minute , second , { _ , 0 } , format ) do
1235- time_to_string_format ( hour , minute , second , format )
1245+ defp time_to_iodata_guarded ( hour , minute , second , { _ , 0 } , format ) do
1246+ time_to_iodata_format ( hour , minute , second , format )
12361247 end
12371248
1238- defp time_to_string_guarded ( hour , minute , second , { microsecond , precision } , format ) do
1239- time_to_string_format ( hour , minute , second , format ) <>
1240- "." <> ( microsecond |> zero_pad ( 6 ) |> binary_part ( 0 , precision ) )
1249+ defp time_to_iodata_guarded ( hour , minute , second , { microsecond , precision } , format ) do
1250+ [
1251+ time_to_iodata_format ( hour , minute , second , format ) ,
1252+ "." ,
1253+ microsecond |> zero_pad ( 6 ) |> IO . iodata_to_binary ( ) |> binary_part ( 0 , precision )
1254+ ]
12411255 end
12421256
1243- defp time_to_string_format ( hour , minute , second , :extended ) do
1244- zero_pad ( hour , 2 ) <> ":" <> zero_pad ( minute , 2 ) <> ":" <> zero_pad ( second , 2 )
1257+ defp time_to_iodata_format ( hour , minute , second , :extended ) do
1258+ [ zero_pad ( hour , 2 ) , ":" , zero_pad ( minute , 2 ) , ":" , zero_pad ( second , 2 ) ]
12451259 end
12461260
1247- defp time_to_string_format ( hour , minute , second , :basic ) do
1248- zero_pad ( hour , 2 ) <> zero_pad ( minute , 2 ) <> zero_pad ( second , 2 )
1261+ defp time_to_iodata_format ( hour , minute , second , :basic ) do
1262+ [ zero_pad ( hour , 2 ) , zero_pad ( minute , 2 ) , zero_pad ( second , 2 ) ]
12491263 end
12501264
12511265 @ doc """
@@ -1273,18 +1287,27 @@ defmodule Calendar.ISO do
12731287 @ doc since: "1.4.0"
12741288 @ spec date_to_string ( year , month , day , :basic | :extended ) :: String . t ( )
12751289 @ impl true
1276- def date_to_string ( year , month , day , format \\ :extended )
1290+ def date_to_string ( year , month , day , format \\ :extended ) do
1291+ date_to_iodata ( year , month , day , format )
1292+ |> IO . iodata_to_binary ( )
1293+ end
1294+
1295+ def date_to_iodata ( year , month , day , format \\ :extended )
12771296 when is_integer ( year ) and is_integer ( month ) and is_integer ( day ) and
12781297 format in [ :basic , :extended ] do
1279- date_to_string_guarded ( year , month , day , format )
1298+ date_to_iodata_guarded ( year , month , day , format )
12801299 end
12811300
1282- defp date_to_string_guarded ( year , month , day , :extended ) do
1283- zero_pad ( year , 4 ) <> "-" <> zero_pad ( month , 2 ) <> "-" <> zero_pad ( day , 2 )
1301+ defp date_to_iodata_guarded ( year , month , day , :extended ) do
1302+ [ zero_pad ( year , 4 ) , "-" , zero_pad ( month , 2 ) , "-" , zero_pad ( day , 2 ) ]
12841303 end
12851304
1286- defp date_to_string_guarded ( year , month , day , :basic ) do
1287- zero_pad ( year , 4 ) <> zero_pad ( month , 2 ) <> zero_pad ( day , 2 )
1305+ defp date_to_iodata_guarded ( year , month , day , :basic ) do
1306+ [
1307+ zero_pad ( year , 4 ) ,
1308+ zero_pad ( month , 2 ) ,
1309+ zero_pad ( day , 2 )
1310+ ]
12881311 end
12891312
12901313 @ doc """
@@ -1327,8 +1350,34 @@ defmodule Calendar.ISO do
13271350 microsecond ,
13281351 format \\ :extended
13291352 ) do
1330- date_to_string ( year , month , day , format ) <>
1331- " " <> time_to_string ( hour , minute , second , microsecond , format )
1353+ naive_datetime_to_iodata (
1354+ year ,
1355+ month ,
1356+ day ,
1357+ hour ,
1358+ minute ,
1359+ second ,
1360+ microsecond ,
1361+ format
1362+ )
1363+ |> IO . iodata_to_binary ( )
1364+ end
1365+
1366+ def naive_datetime_to_iodata (
1367+ year ,
1368+ month ,
1369+ day ,
1370+ hour ,
1371+ minute ,
1372+ second ,
1373+ microsecond ,
1374+ format \\ :extended
1375+ ) do
1376+ [
1377+ date_to_iodata ( year , month , day , format ) ,
1378+ " " ,
1379+ time_to_iodata ( hour , minute , second , microsecond , format )
1380+ ]
13321381 end
13331382
13341383 @ doc """
@@ -1397,17 +1446,27 @@ defmodule Calendar.ISO do
13971446 )
13981447 when is_time_zone ( time_zone ) and is_zone_abbr ( zone_abbr ) and is_utc_offset ( utc_offset ) and
13991448 is_std_offset ( std_offset ) do
1400- date_to_string ( year , month , day , format ) <>
1401- " " <>
1402- time_to_string ( hour , minute , second , microsecond , format ) <>
1403- offset_to_string ( utc_offset , std_offset , time_zone , format ) <>
1404- zone_to_string ( utc_offset , std_offset , zone_abbr , time_zone )
1449+ [
1450+ date_to_iodata ( year , month , day , format ) ,
1451+ " " ,
1452+ time_to_iodata ( hour , minute , second , microsecond , format ) ,
1453+ offset_to_iodata ( utc_offset , std_offset , time_zone , format ) ,
1454+ zone_to_iodata ( utc_offset , std_offset , zone_abbr , time_zone )
1455+ ]
1456+ |> IO . iodata_to_binary ( )
14051457 end
14061458
14071459 @ doc false
14081460 def offset_to_string ( 0 , 0 , "Etc/UTC" , _format ) , do: "Z"
14091461
1410- def offset_to_string ( utc , std , _zone , format ) do
1462+ def offset_to_string ( utc , std , zone , format ) do
1463+ offset_to_iodata ( utc , std , zone , format )
1464+ |> IO . iodata_to_binary ( )
1465+ end
1466+
1467+ def offset_to_iodata ( 0 , 0 , "Etc/UTC" , _format ) , do: "Z"
1468+
1469+ def offset_to_iodata ( utc , std , _zone , format ) do
14111470 total = utc + std
14121471 second = abs ( total )
14131472 minute = second |> rem ( 3600 ) |> div ( 60 )
@@ -1416,15 +1475,15 @@ defmodule Calendar.ISO do
14161475 end
14171476
14181477 defp format_offset ( total , hour , minute , :extended ) do
1419- sign ( total ) <> zero_pad ( hour , 2 ) <> ":" <> zero_pad ( minute , 2 )
1478+ [ sign ( total ) , zero_pad ( hour , 2 ) , ":" , zero_pad ( minute , 2 ) ]
14201479 end
14211480
14221481 defp format_offset ( total , hour , minute , :basic ) do
1423- sign ( total ) <> zero_pad ( hour , 2 ) <> zero_pad ( minute , 2 )
1482+ [ sign ( total ) , zero_pad ( hour , 2 ) , zero_pad ( minute , 2 ) ]
14241483 end
14251484
1426- defp zone_to_string ( _ , _ , _ , "Etc/UTC" ) , do: ""
1427- defp zone_to_string ( _ , _ , abbr , zone ) , do: " " <> abbr <> " " <> zone
1485+ defp zone_to_iodata ( _ , _ , _ , "Etc/UTC" ) , do: ""
1486+ defp zone_to_iodata ( _ , _ , abbr , zone ) , do: [ " " , abbr , " " , zone ]
14281487
14291488 @ doc """
14301489 Determines if the date given is valid according to the proleptic Gregorian calendar.
@@ -1490,11 +1549,20 @@ defmodule Calendar.ISO do
14901549
14911550 defp zero_pad ( val , count ) when val >= 0 do
14921551 num = Integer . to_string ( val )
1493- :binary . copy ( "0" , max ( count - byte_size ( num ) , 0 ) ) <> num
1552+
1553+ case max ( count - byte_size ( num ) , 0 ) do
1554+ 0 -> num
1555+ 1 -> [ "0" , num ]
1556+ 2 -> [ "00" , num ]
1557+ 3 -> [ "000" , num ]
1558+ 4 -> [ "0000" , num ]
1559+ 5 -> [ "00000" , num ]
1560+ 6 -> [ "000000" , num ]
1561+ end
14941562 end
14951563
14961564 defp zero_pad ( val , count ) do
1497- "-" <> zero_pad ( - val , count )
1565+ [ "-" , zero_pad ( - val , count ) ]
14981566 end
14991567
15001568 @ doc """
0 commit comments