@@ -1064,6 +1064,134 @@ level.
10641064 60
10651065
10661066
1067+ Timezones
1068+ =========
1069+
1070+ .. versionchanged :: 0.5
1071+
1072+ ``Pendulum `` provides its own timezone handling and no longer
1073+ rely on ``pytz `` which was not always reliable.
1074+
1075+ Timezones are an important part of every datetime library and ``Pendulum ``
1076+ tries to provide an easy and accurate system to handle them properly.
1077+
1078+ .. note ::
1079+
1080+ The timezone system works best inside the ``pendulum `` ecosystem but
1081+ can also be used with the standard ``datetime `` library with a few limitations.
1082+ See `Using the timezone library directly `_
1083+
1084+ Normalization
1085+ -------------
1086+
1087+ When you create a ``Pendulum `` instance, the library will normalize it for the
1088+ given timezone to properly handle any transition that might have occurred.
1089+
1090+ .. code-block :: python
1091+
1092+ import pendulum
1093+
1094+ pendulum.create(2013 , 3 , 31 , 2 , 30 , 0 , 0 , ' Europe/Paris' )
1095+ # 2:30 for the 31th of March 2013 does not exist
1096+ # so pendulum will return the actual time which is 3:30+02:00
1097+ ' 2013-03-31T03:30:00+02:00'
1098+
1099+ pendulum.create(2013 , 10 , 27 , 2 , 30 , 0 , 0 , ' Europe/Paris' )
1100+ # Here, 2:30 exists twice in the day so pendulum will
1101+ # assume that the transition already occurred
1102+ ' 2013-10-27T02:30:00+01:00'
1103+
1104+
1105+ Shifting time to transition
1106+ ---------------------------
1107+
1108+ So, what happens when you add time to a ``Pendulum `` instance and stumble upon
1109+ a transition time?
1110+ Well, ``Pendulum ``, provided with the context of the previous instance, will
1111+ adopt the proper behavior and apply the transition accordingly.
1112+
1113+ .. code-block :: python
1114+
1115+ import pendulum
1116+
1117+ dt = pendulum.create(2013 , 3 , 31 , 1 , 59 , 59 , 999999 , ' Europe/Paris' )
1118+ ' 2013-03-31T01:59:59.999999+01:00'
1119+ dt = dt.add(microseconds = 1 )
1120+ ' 2013-03-31T03:00:00+02:00'
1121+ dt.subtract(microseconds = 1 )
1122+ ' 2013-03-31T01:59:59.999998+01:00'
1123+
1124+ dt = pendulum.create(2013 , 10 , 27 , 1 , 59 , 59 , 999999 , ' Europe/Paris' )
1125+ dt = dt.add(hours = 1 )
1126+ # We can't just do
1127+ # pendulum.create(2013, 10, 27, 2, 59, 59, 999999, 'Europe/Paris')
1128+ # because of the default normalization
1129+ ' 2013-10-27T02:59:59.999999+02:00'
1130+ dt = dt.add(microseconds = 1 )
1131+ ' 2013-10-27T02:00:00+01:00'
1132+ dt = dt.subtract(microseconds = 1 )
1133+ ' 2013-10-27T02:59:59.999999+02:00'
1134+
1135+ Switching timezones
1136+ -------------------
1137+
1138+ You can easily change the timezone of a ``Pendulum `` instance
1139+ with the ``in_timezone() `` method.
1140+
1141+ .. note ::
1142+
1143+ You can also use the more concise ``in_tz() ``
1144+
1145+ .. code-block :: python
1146+
1147+ in_paris = pendulum.create(2016 , 8 , 7 , 22 , 24 , 30 , tz = ' Europe/Paris' )
1148+ ' 2016-08-07T22:24:30+02:00'
1149+ in_paris.in_timezone(' America/New_York' )
1150+ ' 2016-08-07T16:24:30-04:00'
1151+ in_paris.in_tz(' Asia/Tokyo' )
1152+ ' 2016-08-08T05:24:30+09:00'
1153+
1154+ Using the timezone library directly
1155+ -----------------------------------
1156+
1157+ Like said in the introduction, you can use the timezone library
1158+ directly with standard ``datetime `` objects but with limitations, especially
1159+ when adding and subtracting time around transition times.
1160+
1161+ .. code-block :: python
1162+
1163+ from datetime import datetime, timedelta
1164+ from pendulum import timezone
1165+
1166+ paris = timezone(' Europe/Paris' )
1167+ dt = datetime(2013 , 3 , 31 , 2 , 30 )
1168+ dt = paris.convert(dt)
1169+ dt.isoformat()
1170+ ' 2013-03-31T03:30:00+02:00'
1171+ # Normalization works as expected
1172+
1173+ new_york = timezone(' America/New_York' )
1174+ new_york.convert(dt).isoformat()
1175+ ' 2013-03-30T21:30:00-04:00'
1176+ # Timezone switching works as expected
1177+
1178+ dt = datetime(2013 , 3 , 31 , 1 , 59 , 59 , 999999 )
1179+ dt = paris.convert(dt)
1180+ dt.isoformat()
1181+ ' 2013-03-31T01:59:59.999999+01:00'
1182+ dt = dt + timedelta(microseconds = 1 )
1183+ dt.isoformat()
1184+ ' 2013-03-31T02:00:00+01:00'
1185+ # This does not work as expected.
1186+ # This is a limitation of datetime objects
1187+ # that can't switch around transition times.
1188+ # However, you can use convert()
1189+ # to retrieve the proper datetime.
1190+ dt = tz.convert(dt)
1191+ dt.isoformat()
1192+ ' 2013-03-31T03:00:00+02:00'
1193+
1194+
10671195 Interval
10681196========
10691197
0 commit comments