@@ -720,6 +720,9 @@ defmodule DateTime do
720720 Other time zone databases can be passed as argument or set globally.
721721 See the "Time zone database" section in the module docs.
722722
723+ Shifting to the `"Etc/UTC"` time zone always succeeds without
724+ consulting the `time_zone_database`.
725+
723726 ## Examples
724727
725728 iex> {:ok, pacific_datetime} = DateTime.shift_zone(~U[2018-07-16 10:00:00Z], "America/Los_Angeles", FakeTimeZoneDatabase)
@@ -753,6 +756,28 @@ defmodule DateTime do
753756 |> shift_zone_for_iso_days_utc ( calendar , precision , time_zone , time_zone_database )
754757 end
755758
759+ defp shift_zone_for_iso_days_utc ( iso_days_utc , calendar , precision , "Etc/UTC" , _time_zone_db ) do
760+ { year , month , day , hour , minute , second , { microsecond , _ } } =
761+ calendar . naive_datetime_from_iso_days ( iso_days_utc )
762+
763+ datetime = % DateTime {
764+ calendar: calendar ,
765+ year: year ,
766+ month: month ,
767+ day: day ,
768+ hour: hour ,
769+ minute: minute ,
770+ second: second ,
771+ microsecond: { microsecond , precision } ,
772+ std_offset: 0 ,
773+ utc_offset: 0 ,
774+ zone_abbr: "UTC" ,
775+ time_zone: "Etc/UTC"
776+ }
777+
778+ { :ok , datetime }
779+ end
780+
756781 defp shift_zone_for_iso_days_utc ( iso_days_utc , calendar , precision , time_zone , time_zone_db ) do
757782 case time_zone_db . time_zone_period_from_utc_iso_days ( iso_days_utc , time_zone ) do
758783 { :ok , % { std_offset: std_offset , utc_offset: utc_offset , zone_abbr: zone_abbr } } ->
@@ -1708,44 +1733,6 @@ defmodule DateTime do
17081733 add ( datetime , amount_to_add * 60 , :second , time_zone_database )
17091734 end
17101735
1711- def add (
1712- % { calendar: calendar , time_zone: "Etc/UTC" } = datetime ,
1713- amount_to_add ,
1714- unit ,
1715- _time_zone_database
1716- )
1717- when is_integer ( amount_to_add ) do
1718- % { microsecond: { _ , precision } } = datetime
1719-
1720- if not is_integer ( unit ) and unit not in ~w( second millisecond microsecond nanosecond) a do
1721- raise ArgumentError ,
1722- "unsupported time unit. Expected :day, :hour, :minute, :second, :millisecond, :microsecond, :nanosecond, or a positive integer, got #{ inspect ( unit ) } "
1723- end
1724-
1725- precision = max ( Calendar.ISO . time_unit_to_precision ( unit ) , precision )
1726-
1727- { year , month , day , hour , minute , second , { microsecond , _ } } =
1728- datetime
1729- |> to_iso_days ( )
1730- |> Calendar.ISO . shift_time_unit ( amount_to_add , unit )
1731- |> calendar . naive_datetime_from_iso_days ( )
1732-
1733- % DateTime {
1734- calendar: calendar ,
1735- year: year ,
1736- month: month ,
1737- day: day ,
1738- hour: hour ,
1739- minute: minute ,
1740- second: second ,
1741- microsecond: { microsecond , precision } ,
1742- time_zone: "Etc/UTC" ,
1743- zone_abbr: "UTC" ,
1744- utc_offset: 0 ,
1745- std_offset: 0
1746- }
1747- end
1748-
17491736 def add ( % { calendar: calendar } = datetime , amount_to_add , unit , time_zone_database )
17501737 when is_integer ( amount_to_add ) do
17511738 % {
@@ -1785,6 +1772,9 @@ defmodule DateTime do
17851772
17861773 Allowed units are: `:year`, `:month`, `:week`, `:day`, `:hour`, `:minute`, `:second`, `:microsecond`.
17871774
1775+ If the datetime is in the `"Etc/UTC"` time zone, this function
1776+ always succeeds without consulting the `time_zone_database`.
1777+
17881778 This operation is equivalent to shifting the datetime wall clock
17891779 (in other words, the value as someone in that timezone would see
17901780 on their watch), then applying the time zone offset to convert it
@@ -1853,44 +1843,6 @@ defmodule DateTime do
18531843 @ spec shift ( Calendar . datetime ( ) , Duration . duration ( ) , Calendar . time_zone_database ( ) ) :: t
18541844 def shift ( datetime , duration , time_zone_database \\ Calendar . get_time_zone_database ( ) )
18551845
1856- def shift ( % { calendar: calendar , time_zone: "Etc/UTC" } = datetime , duration , _time_zone_database ) do
1857- % {
1858- year: year ,
1859- month: month ,
1860- day: day ,
1861- hour: hour ,
1862- minute: minute ,
1863- second: second ,
1864- microsecond: microsecond
1865- } = datetime
1866-
1867- { year , month , day , hour , minute , second , microsecond } =
1868- calendar . shift_naive_datetime (
1869- year ,
1870- month ,
1871- day ,
1872- hour ,
1873- minute ,
1874- second ,
1875- microsecond ,
1876- __duration__! ( duration )
1877- )
1878-
1879- % DateTime {
1880- year: year ,
1881- month: month ,
1882- day: day ,
1883- hour: hour ,
1884- minute: minute ,
1885- second: second ,
1886- microsecond: microsecond ,
1887- time_zone: "Etc/UTC" ,
1888- zone_abbr: "UTC" ,
1889- std_offset: 0 ,
1890- utc_offset: 0
1891- }
1892- end
1893-
18941846 def shift ( % { calendar: calendar } = datetime , duration , time_zone_database ) do
18951847 % {
18961848 year: year ,
0 commit comments