22
33import datetime
44import pytz
5- from babel import numbers
5+ import six
66
7- import ckan .lib .i18n as i18n
7+ from flask_babel import (
8+ format_number ,
9+ format_datetime ,
10+ format_date ,
11+ format_timedelta
12+ )
813
9- from ckan .common import _ , ungettext
10-
11-
12- ##################################################
13- # #
14- # Month translations #
15- # #
16- ##################################################
17-
18- def _month_jan ():
19- return _ ('January' )
20-
21-
22- def _month_feb ():
23- return _ ('February' )
24-
25-
26- def _month_mar ():
27- return _ ('March' )
28-
29-
30- def _month_apr ():
31- return _ ('April' )
32-
33-
34- def _month_may ():
35- return _ ('May' )
36-
37-
38- def _month_june ():
39- return _ ('June' )
40-
41-
42- def _month_july ():
43- return _ ('July' )
44-
45-
46- def _month_aug ():
47- return _ ('August' )
48-
49-
50- def _month_sept ():
51- return _ ('September' )
52-
53-
54- def _month_oct ():
55- return _ ('October' )
56-
57-
58- def _month_nov ():
59- return _ ('November' )
60-
61-
62- def _month_dec ():
63- return _ ('December' )
64-
65-
66- # _MONTH_FUNCTIONS provides an easy way to get a localised month via
67- # _MONTH_FUNCTIONS[month]() where months are zero based ie jan = 0, dec = 11
68- _MONTH_FUNCTIONS = [_month_jan , _month_feb , _month_mar , _month_apr ,
69- _month_may , _month_june , _month_july , _month_aug ,
70- _month_sept , _month_oct , _month_nov , _month_dec ]
14+ from ckan .common import _
7115
7216
7317def localised_nice_date (datetime_ , show_date = False , with_hours = False ,
74- with_seconds = False ):
18+ with_seconds = False , format = None ):
7519 ''' Returns a friendly localised unicode representation of a datetime.
7620 e.g. '31 minutes ago'
7721 '1 day ago'
7822 'April 24, 2013' (show_date=True)
23+ 'October 25, 2017, 16:03 (UTC)' (show_date=True, with_hours=True)
24+ 'Apr 3, 2020, 4:00:31 PM' (
25+ show_date=True, with_hours=True, format='medium')
26+ 'April 03, 20' (show_date=True, format='MMMM dd, YY')
7927
8028 :param datetime_: The date to format
8129 :type datetime_: datetime
@@ -85,95 +33,42 @@ def localised_nice_date(datetime_, show_date=False, with_hours=False,
8533 :type with_hours: bool
8634 :param with_seconds: should the `hours:mins:seconds` be shown for dates
8735 :type with_seconds: bool
36+ :param format: override format of datetime representation using babel
37+ date/time pattern syntax of predefined pattern.
38+ :type format: str
39+
8840
8941 :rtype: sting
9042 '''
91-
92- def months_between (date1 , date2 ):
93- if date1 > date2 :
94- date1 , date2 = date2 , date1
95- m1 = date1 .year * 12 + date1 .month
96- m2 = date2 .year * 12 + date2 .month
97- months = m2 - m1
98- if date1 .day > date2 .day :
99- months -= 1
100- elif date1 .day == date2 .day :
101- seconds1 = date1 .hour * 3600 + date1 .minute + date1 .second
102- seconds2 = date2 .hour * 3600 + date2 .minute + date2 .second
103- if seconds1 > seconds2 :
104- months -= 1
105- return months
106-
43+ if datetime_ .tzinfo is None :
44+ datetime_ = datetime_ .replace (tzinfo = pytz .utc )
10745 if not show_date :
10846 now = datetime .datetime .now (pytz .utc )
109- if datetime_ .tzinfo is None :
110- datetime_ = datetime_ .replace (tzinfo = pytz .utc )
111-
112- date_diff = now - datetime_
113- days = date_diff .days
114- if days < 1 and now > datetime_ :
115- # less than one day
116- seconds = date_diff .seconds
117- if seconds < 3600 :
118- # less than one hour
119- if seconds < 60 :
120- return _ ('Just now' )
121- else :
122- return ungettext ('{mins} minute ago' , '{mins} minutes ago' ,
123- seconds // 60 ).format (mins = seconds // 60 )
124- else :
125- return ungettext ('{hours} hour ago' , '{hours} hours ago' ,
126- seconds // 3600 ).format (hours = seconds // 3600 )
127- # more than one day
128- months = months_between (datetime_ , now )
129-
130- if months < 1 :
131- return ungettext ('{days} day ago' , '{days} days ago' ,
132- days ).format (days = days )
133- if months < 13 :
134- return ungettext ('{months} month ago' , '{months} months ago' ,
135- months ).format (months = months )
136- return ungettext ('over {years} year ago' , 'over {years} years ago' ,
137- months // 12 ).format (years = months // 12 )
138-
139- # actual date
140- details = {
141- 'sec' : int (datetime_ .second ),
142- 'min' : datetime_ .minute ,
143- 'hour' : datetime_ .hour ,
144- 'day' : datetime_ .day ,
145- 'year' : datetime_ .year ,
146- 'month' : _MONTH_FUNCTIONS [datetime_ .month - 1 ](),
147- 'timezone' : datetime_ .tzname (),
148- }
47+ date_diff = datetime_ - now
48+ if abs (date_diff ) < datetime .timedelta (seconds = 1 ):
49+ return _ ('Just now' )
50+ return format_timedelta (date_diff , add_direction = True )
14951
15052 if with_seconds :
151- return (
152- # Example output: `April 24, 2013, 10:45:21 (Europe/Zurich)`
153- _ ('{month} {day}, {year}, {hour:02}:{min:02}:{sec:02} ({timezone})' ) \
154- .format (** details ))
53+ return format_datetime (datetime_ , format or 'long' )
15554 elif with_hours :
156- return (
157- # Example output: `April 24, 2013, 10:45 (Europe/Zurich)`
158- _ ('{month} {day}, {year}, {hour:02}:{min:02} ({timezone})' ) \
159- .format (** details ))
55+ fmt_str = "MMMM d, YYYY, HH:mm (z)"
56+ return format_datetime (datetime_ , format or fmt_str )
16057 else :
161- return (
162- # Example output: `April 24, 2013`
163- _ ('{month} {day}, {year}' ).format (** details ))
58+ return format_date (datetime_ , format or 'long' )
16459
16560
16661def localised_number (number ):
16762 ''' Returns a localised unicode representation of number '''
168- return numbers . format_number (number , locale = i18n . get_lang () )
63+ return format_number (number )
16964
17065
17166def localised_filesize (number ):
17267 ''' Returns a localised unicode representation of a number in bytes, MiB
17368 etc '''
17469 def rnd (number , divisor ):
17570 # round to 1 decimal place
176- return localised_number (float (number * 10 / divisor ) / 10 )
71+ return localised_number (float (number * 10 // divisor ) / 10 )
17772
17873 if number < 1024 :
17974 return _ ('{bytes} bytes' ).format (bytes = localised_number (number ))
@@ -193,7 +88,7 @@ def localised_SI_number(number):
19388
19489 def rnd (number , divisor ):
19590 # round to 1 decimal place
196- return localised_number (float (number * 10 / divisor ) / 10 )
91+ return localised_number (float (number * 10 // divisor ) / 10 )
19792
19893 if number < 1000 :
19994 return _ ('{n}' ).format (n = localised_number (number ))
0 commit comments