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