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 63 2007-01-02 09:22:16Z the.pythy $"
22 __url__ = "$URL: https://pythy.googlecode.com/svn/trunk/pytils/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"понедельник"),
71 (u"вт", u"вторник", u"вторник"),
72 (u"ср", u"среда", u"среду"),
73 (u"чт", u"четверг", u"четверг"),
74 (u"пт", u"пятница", u"пятницу"),
75 (u"сб", u"суббота", u"субботу"),
76 (u"вск", u"воскресенье", u"субботу"),
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 \
173 alternatives and alternatives[0]
174 _result_str = alter_str or real_str
175 result_str = in_future and u"%s %s" % (PREFIX_IN, _result_str) \
176 or u"%s %s" % (_result_str, SUFFIX_AGO)
177
178
179
180 zero_str = minutes == 0 and not real_words and \
181 (in_future and u"менее чем через минуту" \
182 or u"менее минуты назад")
183
184
185
186 day_alternatives = DAY_ALTERNATIVES.get(days, False)
187 alternate_day = day_alternatives and current and limit == 1 and \
188 ((in_future and day_alternatives[1]) \
189 or day_alternatives[0])
190
191 final_str = not real_words and zero_str or alternate_day or result_str
192
193 return final_str
194
195
196 -def ru_strftime(format=u"%d.%m.%Y", date=None, inflected=False, inflected_day=False):
197 """
198 Russian strftime without locale
199
200 @param format: strftime format, default=u'%d.%m.%Y'
201 @type format: C{unicode}
202
203 @param date: date value, default=None translates to today
204 @type date: C{datetime.date} or C{datetime.datetime}
205
206 @return: strftime string
207 @rtype: unicode
208
209 @raise TypeError: input parameters' check failed
210 """
211 if date is None:
212 date = datetime.datetime.today()
213 utils.check_type('date', (datetime.date, datetime.datetime))
214 utils.check_type('format', unicode)
215
216 midx = inflected and 2 or 1
217 didx = inflected_day and 2 or 1
218
219 format = format.replace(u'%a', DAY_NAMES[date.weekday()][0])
220 format = format.replace(u'%A', DAY_NAMES[date.weekday()][didx])
221 format = format.replace(u'%b', MONTH_NAMES[date.month-1][0])
222 format = format.replace(u'%B', MONTH_NAMES[date.month-1][midx])
223
224
225 s_format = format.encode("utf-8")
226 s_res = date.strftime(s_format)
227
228 u_res = s_res.decode("utf-8")
229
230 return u_res
231