1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 Russian dates without locales
19 """
20
21 __id__ = __revision__ = "$Id: dt.py 102 2007-07-12 12:33:36Z the.pythy $"
22 __url__ = "$URL: https://pythy.googlecode.com/svn/tags/pytils/0_2_2/pytils/dt.py $"
23
24 import datetime
25
26 from pytils import numeral, utils
27
28 DAY_ALTERNATIVES = {
29 1: (u"вчера", u"завтра"),
30 2: (u"позавчера", u"послезавтра")
31 }
32
33 DAY_VARIANTS = (
34 u"день",
35 u"дня",
36 u"дней",
37 )
38
39 HOUR_VARIANTS = (
40 u"час",
41 u"часа",
42 u"часов",
43 )
44
45 MINUTE_VARIANTS = (
46 u"минуту",
47 u"минуты",
48 u"минут",
49 )
50
51 PREFIX_IN = u"через"
52 SUFFIX_AGO = u"назад"
53
54 MONTH_NAMES = (
55 (u"янв", u"январь", u"января"),
56 (u"фев", u"февраль", u"февраля"),
57 (u"мар", u"март", u"марта"),
58 (u"апр", u"апрель", u"апреля"),
59 (u"май", u"май", u"мая"),
60 (u"июн", u"июнь", u"июня"),
61 (u"июл", u"июль", u"июля"),
62 (u"авг", u"август", u"августа"),
63 (u"сен", u"сентябрь", u"сентября"),
64 (u"окт", u"октябрь", u"октября"),
65 (u"ноя", u"ноябрь", u"ноября"),
66 (u"дек", u"декабрь", u"декабря"),
67 )
68
69 DAY_NAMES = (
70 (u"пн", u"понедельник", u"понедельник", u"в\xa0"),
71 (u"вт", u"вторник", u"вторник", u"во\xa0"),
72 (u"ср", u"среда", u"среду", u"в\xa0"),
73 (u"чт", u"четверг", u"четверг", u"в\xa0"),
74 (u"пт", u"пятница", u"пятницу", u"в\xa0"),
75 (u"сб", u"суббота", u"субботу", u"в\xa0"),
76 (u"вск", u"воскресенье", u"воскресенье", u"в\xa0")
77 )
78
79
81 """
82 Represents distance of time in words
83
84 @param from_time: source time (in seconds from epoch)
85 @type from_time: C{int}, C{float} or C{datetime.datetime}
86
87 @param accuracy: level of accuracy (1..3), default=1
88 @type accuracy: C{int}
89
90 @param to_time: target time (in seconds from epoch),
91 default=None translates to current time
92 @type to_time: C{int}, C{float} or C{datetime.datetime}
93
94 @return: distance of time in words
95 @rtype: unicode
96
97 @raise TypeError: input parameters' check failed
98 @raise ValueError: accuracy is lesser or equal zero
99 """
100 current = False
101
102 if to_time is None:
103 current = True
104 to_time = datetime.datetime.now()
105
106 utils.check_type('from_time', (int, float, datetime.datetime))
107 utils.check_type('to_time', (int, float, datetime.datetime))
108 utils.check_type('accuracy', int)
109 utils.check_positive('accuracy', strict=True)
110
111 if not isinstance(from_time, datetime.datetime):
112 from_time = datetime.datetime.fromtimestamp(from_time)
113
114 if not isinstance(to_time, datetime.datetime):
115 to_time = datetime.datetime.fromtimestamp(to_time)
116
117 dt_delta = to_time - from_time
118 difference = dt_delta.days*86400 + dt_delta.seconds
119
120 seconds_orig = int(abs(difference))
121 minutes_orig = int(abs(difference)/60.0)
122 hours_orig = int(abs(difference)/3600.0)
123 days_orig = int(abs(difference)/86400.0)
124 in_future = from_time > to_time
125
126 words = []
127 values = []
128 alternatives = []
129
130 days = days_orig
131 hours = hours_orig - days_orig*24
132
133 words.append(u"%d %s" % (days, numeral.choose_plural(days, DAY_VARIANTS)))
134 values.append(days)
135
136 words.append(u"%d %s" % \
137 (hours, numeral.choose_plural(hours, HOUR_VARIANTS)))
138 values.append(hours)
139
140 hours == 1 and current and alternatives.append(u"час")
141
142 minutes = minutes_orig - hours_orig*60
143
144 words.append(u"%d %s" % (minutes,
145 numeral.choose_plural(minutes, MINUTE_VARIANTS)))
146 values.append(minutes)
147
148 minutes == 1 and current and alternatives.append(u"минуту")
149
150 real_words = words
151
152 while values and not values[-1]:
153 values.pop()
154 words.pop()
155
156 while values and not values[0]:
157 values.pop(0)
158 words.pop(0)
159 limit = min(accuracy, len(words))
160 real_words = words[:limit]
161 real_values = values[:limit]
162
163 while real_values and not real_values[-1]:
164 real_values.pop()
165 real_words.pop()
166 limit -= 1
167
168 real_str = u" ".join(real_words)
169
170
171
172 alter_str = limit == 1 and current and alternatives and \
173 not (days and hours==1) and \
174 not (hours and minutes==1) and \
175 alternatives[0]
176 _result_str = alter_str or real_str
177 result_str = in_future and u"%s %s" % (PREFIX_IN, _result_str) \
178 or u"%s %s" % (_result_str, SUFFIX_AGO)
179
180
181
182 zero_str = minutes == 0 and not real_words and \
183 (in_future and u"менее чем через минуту" \
184 or u"менее минуты назад")
185
186
187
188 day_alternatives = DAY_ALTERNATIVES.get(days, False)
189 alternate_day = day_alternatives and current and limit == 1 and \
190 ((in_future and day_alternatives[1]) \
191 or day_alternatives[0])
192
193 final_str = not real_words and zero_str or alternate_day or result_str
194
195 return final_str
196
197
198 -def ru_strftime(format=u"%d.%m.%Y", date=None, inflected=False, inflected_day=False, preposition=False):
199 """
200 Russian strftime without locale
201
202 @param format: strftime format, default=u'%d.%m.%Y'
203 @type format: C{unicode}
204
205 @param date: date value, default=None translates to today
206 @type date: C{datetime.date} or C{datetime.datetime}
207
208 @param inflected: is month inflected, default False
209 @type inflected: C{bool}
210
211 @param inflected_day: is day inflected, default False
212 @type inflected: C{bool}
213
214 @param preposition: is preposition used, default False
215 preposition=True automatically implies inflected_day=True
216 @type preposition: C{bool}
217
218 @return: strftime string
219 @rtype: unicode
220
221 @raise TypeError: input parameters' check failed
222 """
223 if date is None:
224 date = datetime.datetime.today()
225 utils.check_type('date', (datetime.date, datetime.datetime))
226 utils.check_type('format', unicode)
227
228 weekday = date.weekday()
229
230 prepos = preposition and DAY_NAMES[weekday][3] or u""
231
232 month_idx = inflected and 2 or 1
233 day_idx = (inflected_day or preposition) and 2 or 1
234
235
236
237 if u'%b' in format or u'%B' in format:
238 format = format.replace(u'%d', unicode(date.day))
239
240 format = format.replace(u'%a', prepos+DAY_NAMES[weekday][0])
241 format = format.replace(u'%A', prepos+DAY_NAMES[weekday][day_idx])
242 format = format.replace(u'%b', MONTH_NAMES[date.month-1][0])
243 format = format.replace(u'%B', MONTH_NAMES[date.month-1][month_idx])
244
245
246 s_format = format.encode("utf-8")
247 s_res = date.strftime(s_format)
248
249 u_res = s_res.decode("utf-8")
250
251 return u_res
252