22
33from __future__ import division
44
5- import re
65import time as _time
76import math
87import calendar
98import datetime
9+ import warnings
1010import locale as _locale
1111
1212from contextlib import contextmanager
1818from .mixins .default import TranslatableMixin
1919from .tz import Timezone , UTC , FixedTimezone , local_timezone
2020from .tz .timezone_info import TimezoneInfo
21+ from .formatting import FORMATTERS
2122from ._compat import PY33 , basestring
2223from .constants import (
2324 SUNDAY , MONDAY , TUESDAY , WEDNESDAY ,
@@ -78,9 +79,6 @@ class Pendulum(datetime.datetime, TranslatableMixin):
7879
7980 _EPOCH = datetime .datetime (1970 , 1 , 1 , tzinfo = UTC )
8081
81- _CUSTOM_FORMATTERS = ['_z' , '_t' ]
82- _FORMATTERS_REGEX = re .compile ('%%(%s)' % '|' .join (_CUSTOM_FORMATTERS ))
83-
8482 _MODIFIERS_VALID_UNITS = ['day' , 'week' , 'month' , 'year' , 'decade' , 'century' ]
8583
8684 _TRANSITION_RULE = Timezone .POST_TRANSITION
@@ -885,25 +883,28 @@ def set_to_string_format(cls, fmt):
885883 """
886884 cls ._to_string_format = fmt
887885
888- def format (self , fmt , locale = None ):
886+ def format (self , fmt , locale = None , formatter = None ):
889887 """
890888 Formats the Pendulum instance using the given format.
891889
892890 :param fmt: The format to use
893891 :type fmt: str
894892
893+ :param locale: The locale to use
894+ :type locale: str or None
895+
896+ :param formatter: The formatter to use
897+ :type formatter: str or None
898+
895899 :rtype: str
896900 """
897- if not locale :
898- locale = self .get_locale ()
899-
900- # Checking for custom formatters
901- fmt = self ._FORMATTERS_REGEX .sub (lambda m : self ._strftime (m , locale ), fmt )
901+ if formatter is None :
902+ formatter = 'classic'
902903
903- # Checking for localizable directives
904- fmt = re . sub ( '%(a|A|b|B|p)' , lambda m : self . _localize_directive ( m . group ( 1 ), locale ), fmt )
904+ if formatter not in FORMATTERS :
905+ raise ValueError ( 'Invalid formatter [{}]' . format ( formatter ) )
905906
906- return self . _datetime . strftime ( fmt )
907+ return FORMATTERS [ formatter ]. format ( self , fmt , locale )
907908
908909 def strftime (self , fmt ):
909910 """
@@ -914,78 +915,7 @@ def strftime(self, fmt):
914915
915916 :rtype: str
916917 """
917- # Checking for custom formatters
918- fmt = self ._FORMATTERS_REGEX .sub (self ._strftime , fmt )
919-
920- return self ._datetime .strftime (fmt )
921-
922- def _localize_directive (self , directive , locale ):
923- """
924- Localize a native strftime directive.
925-
926- :param directive: The directive to localize
927- :type directive: str
928-
929- :param locale: The locale to use for localization
930- :type locale: str
931-
932- :rtype: str
933- """
934- if directive == 'a' :
935- id = 'days_abbrev'
936- number = self .day_of_week
937- elif directive == 'A' :
938- id = 'days'
939- number = self .day_of_week
940- elif directive == 'b' :
941- id = 'months_abbrev'
942- number = self .month
943- elif directive == 'B' :
944- id = 'months'
945- number = self .month
946- elif directive == 'p' :
947- id = 'meridian'
948- number = self .hour
949- else :
950- raise ValueError ('Unlocalizable directive [{}]' .format (directive ))
951-
952- translation = self .translator ().transchoice (id , number , locale = locale )
953- if translation == id :
954- return ''
955-
956- return translation
957-
958- def _strftime (self , m , locale = None ):
959- """
960- Handles custom formatters in format string.
961-
962- :return: str
963- """
964- if not locale :
965- locale = _locale .getlocale ()[0 ]
966-
967- fmt = m .group (1 )
968-
969- if fmt == '_z' :
970- offset = self ._datetime .utcoffset () or datetime .timedelta ()
971- minutes = offset .total_seconds () / 60
972-
973- if minutes >= 0 :
974- sign = '+'
975- else :
976- sign = '-'
977-
978- hour , minute = divmod (abs (int (minutes )), 60 )
979-
980- return '{0}{1:02d}:{2:02d}' .format (sign , hour , minute )
981- elif fmt == '_t' :
982- translation = self .translator ().transchoice ('ordinal' , self .day , locale = locale )
983- if translation == 'ordinal' :
984- translation = ''
985-
986- return translation
987-
988- raise ValueError ('Unknown formatter %%{}' .format (fmt ))
918+ return self .format (fmt , _locale .getlocale ()[0 ], 'classic' )
989919
990920 def __str__ (self ):
991921 if self ._to_string_format is None :
0 commit comments