1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 from datetime import datetime
20 import re
21
22 from timelinelib.calendar.gregorian.timetype import GregorianTimeType
23 from timelinelib.calendar.coptic.coptic import CopticDateTime
24 from timelinelib.calendar.coptic.monthnames import abbreviated_name_of_month
25 from timelinelib.calendar.coptic.time import CopticDelta
26 from timelinelib.calendar.coptic.time import CopticTime
27 from timelinelib.calendar.coptic.time import SECONDS_IN_DAY
28 from timelinelib.calendar.coptic.weekdaynames import abbreviated_name_of_weekday
29 from timelinelib.canvas.data import TimeOutOfRangeLeftError
30 from timelinelib.canvas.data import TimeOutOfRangeRightError
31 from timelinelib.canvas.data import TimePeriod
32 from timelinelib.canvas.data import time_period_center
33 from timelinelib.canvas.drawing.interface import Strip
34 from timelinelib.calendar.gregorian.gregorian import gregorian_ymd_to_julian_day
35 from timelinelib.calendar.coptic.coptic import julian_day_to_coptic_ymd
36
37
38 BC = _("BC")
42
45
48
50 match = re.search(r"^(-?\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$", time_string)
51 if match:
52 year = int(match.group(1))
53 month = int(match.group(2))
54 day = int(match.group(3))
55 hour = int(match.group(4))
56 minute = int(match.group(5))
57 second = int(match.group(6))
58 try:
59 return CopticDateTime(year, month, day, hour, minute, second).to_time()
60 except ValueError:
61 raise ValueError("Invalid time, time string = '%s'" % time_string)
62 else:
63 raise ValueError("Time not on correct format = '%s'" % time_string)
64
66 return [
67 (_("Go to &Today") + "\tCtrl+T", go_to_today_fn),
68 (_("Go to &Date...") + "\tCtrl+G", go_to_date_fn),
69 ("SEP", None),
70 (_("Backward") + "\tPgUp", backward_fn),
71 (_("Forward") + "\tPgDn", forward_fn),
72 (_("Forward One Wee&k") + "\tCtrl+K", forward_one_week_fn),
73 (_("Back One &Week") + "\tCtrl+W", backward_one_week_fn),
74 (_("Forward One Mont&h") + "\tCtrl+H", forward_one_month_fn),
75 (_("Back One &Month") + "\tCtrl+M", backward_one_month_fn),
76 (_("Forward One Yea&r") + "\tCtrl+R", forward_one_year_fn),
77 (_("Back One &Year") + "\tCtrl+Y", backward_one_year_fn),
78 ("SEP", None),
79 (_("Fit Millennium"), fit_millennium_fn),
80 (_("Fit Century"), create_strip_fitter(StripCentury)),
81 (_("Fit Decade"), create_strip_fitter(StripDecade)),
82 (_("Fit Year"), create_strip_fitter(StripYear)),
83 (_("Fit Month"), create_strip_fitter(StripMonth)),
84 (_("Fit Week"), fit_week_fn),
85 (_("Fit Day"), create_strip_fitter(StripDay)),
86 ]
87
92
93 def label_without_time(time):
94 coptic_datetime = CopticDateTime.from_time(time)
95 return "%s %s %s" % (
96 coptic_datetime.day,
97 abbreviated_name_of_month(coptic_datetime.month),
98 format_year(coptic_datetime.year)
99 )
100
101 def time_label(time):
102 return "%02d:%02d" % time.get_time_of_day()[:-1]
103 if time_period.is_period():
104 if has_nonzero_time(time_period):
105 label = "%s to %s" % (label_with_time(time_period.start_time),
106 label_with_time(time_period.end_time))
107 else:
108 label = "%s to %s" % (label_without_time(time_period.start_time),
109 label_without_time(time_period.end_time))
110 else:
111 if has_nonzero_time(time_period):
112 label = "%s" % label_with_time(time_period.start_time)
113 else:
114 label = "%s" % label_without_time(time_period.start_time)
115 return label
116
122
125
128
130 """
131 Return a tuple (major_strip, minor_strip) for current time period and
132 window size.
133 """
134 day_period = TimePeriod(CopticTime(0, 0),CopticTime(1, 0))
135 one_day_width = metrics.calc_exact_width(day_period)
136 if one_day_width > 20000:
137 return (StripHour(), StripMinute())
138 elif one_day_width > 600:
139 return (StripDay(), StripHour())
140 elif one_day_width > 45:
141 return (StripWeek(appearance), StripWeekday())
142 elif one_day_width > 25:
143 return (StripMonth(), StripDay())
144 elif one_day_width > 1.5:
145 return (StripYear(), StripMonth())
146 elif one_day_width > 0.12:
147 return (StripDecade(), StripYear())
148 elif one_day_width > 0.012:
149 return (StripCentury(), StripDecade())
150 else:
151 return (StripCentury(), StripCentury())
152
155
158
161
175
178
181
189
192
195
196
198 return time.julian_day % 7
199
203
207
211
212
213 -def go_to_date_fn(main_frame, current_period, navigation_fn):
214 def navigate_to(time):
215 navigation_fn(lambda tp: tp.center(time))
216 main_frame.display_time_editor_dialog(
217 CopticTimeType(), current_period.mean_time(), navigate_to, _("Go to Date"))
218
219
220 -def backward_fn(main_frame, current_period, navigation_fn):
221 _move_page_smart(current_period, navigation_fn, -1)
222
223
224 -def forward_fn(main_frame, current_period, navigation_fn):
225 _move_page_smart(current_period, navigation_fn, 1)
226
227
228 -def _move_page_smart(current_period, navigation_fn, direction):
229 if _whole_number_of_years(current_period):
230 _move_page_years(current_period, navigation_fn, direction)
231 elif _whole_number_of_months(current_period):
232 _move_page_months(current_period, navigation_fn, direction)
233 else:
234 navigation_fn(lambda tp: tp.move_delta(direction * current_period.delta()))
235
238 """
239 >>> from timelinelib.test.utils import gregorian_period
240
241 >>> _whole_number_of_years(gregorian_period("11 Sep 2013", "11 Sep 2014"))
242 True
243
244 >>> _whole_number_of_years(gregorian_period("9 Sep 1776", "9 Sep 1777"))
245 True
246
247 >>> _whole_number_of_years(gregorian_period("8 Dec 1776", "8 Dec 1777"))
248 False
249
250 >>> _whole_number_of_years(gregorian_period("6 Sep 2013", "11 Sep 2014"))
251 False
252 """
253 return (CopticDateTime.from_time(period.start_time).is_first_day_in_year() and
254 CopticDateTime.from_time(period.end_time).is_first_day_in_year() and
255 _calculate_year_diff(period) > 0)
256
257
258 -def _move_page_years(curret_period, navigation_fn, direction):
259 def navigate(tp):
260 year_delta = direction * _calculate_year_diff(curret_period)
261 coptic_start = CopticDateTime.from_time(curret_period.start_time)
262 coptic_end = CopticDateTime.from_time(curret_period.end_time)
263 new_start_year = coptic_start.year + year_delta
264 new_end_year = coptic_end.year + year_delta
265 try:
266 new_start = coptic_start.replace(year=new_start_year).to_time()
267 new_end = coptic_end.replace(year=new_end_year).to_time()
268 if new_end > CopticTimeType().get_max_time():
269 raise ValueError()
270 if new_start < CopticTimeType().get_min_time():
271 raise ValueError()
272 except ValueError:
273 if direction < 0:
274 raise TimeOutOfRangeLeftError()
275 else:
276 raise TimeOutOfRangeRightError()
277 return tp.update(new_start, new_end)
278 navigation_fn(navigate)
279
284
287
288 """
289 >>> from timelinelib.test.utils import gregorian_period
290
291 >>> _whole_number_of_months(gregorian_period("9 Jan 2013", "9 Jan 2014"))
292 True
293
294 >>> _whole_number_of_months(gregorian_period("6 Jul 1776", "6 Jul 1777"))
295 True
296
297 >>> _whole_number_of_months(gregorian_period("2 Jan 2013", "2 Mar 2014"))
298 False
299
300 >>> _whole_number_of_months(gregorian_period("1 Jan 2013 12:00", "1 Mar 2014"))
301 False
302 """
303 start, end = CopticDateTime.from_time(period.start_time), CopticDateTime.from_time(period.end_time)
304 start_months = start.year * 13 + start.month
305 end_months = end.year * 13 + end.month
306 month_diff = end_months - start_months
307
308 return (start.is_first_of_month() and
309 end.is_first_of_month() and
310 month_diff > 0)
311
312
313 -def _move_page_months(curret_period, navigation_fn, direction):
314 def navigate(tp):
315 start = CopticDateTime.from_time(curret_period.start_time)
316 end = CopticDateTime.from_time(curret_period.end_time)
317 start_months = start.year * 13 + start.month
318 end_months = end.year * 13 + end.month
319 month_diff = end_months - start_months
320 month_delta = month_diff * direction
321 new_start_year, new_start_month = _months_to_year_and_month(start_months + month_delta)
322 new_end_year, new_end_month = _months_to_year_and_month(end_months + month_delta)
323 try:
324 new_start = start.replace(year=new_start_year, month=new_start_month)
325 new_end = end.replace(year=new_end_year, month=new_end_month)
326 start = new_start.to_time()
327 end = new_end.to_time()
328 if end > CopticTimeType().get_max_time():
329 raise ValueError()
330 if start < CopticTimeType().get_min_time():
331 raise ValueError()
332 except ValueError:
333 if direction < 0:
334 raise TimeOutOfRangeLeftError()
335 else:
336 raise TimeOutOfRangeRightError()
337 return tp.update(start, end)
338 navigation_fn(navigate)
339
342 years = int(months // 13)
343 month = months - years * 13
344 if month == 0:
345 month = 13
346 years -= 1
347 return years, month
348
353
358
374
378
382
387
392
403
407
411
412
413 -def fit_week_fn(main_frame, current_period, navigation_fn):
422
431 navigation_fn(navigate)
432 return fit
433
436
437 """
438 Year Name | Year integer | Decade name
439 ----------+--------------+------------
440 .. | .. |
441 200 BC | -199 | 200s BC (100 years)
442 ----------+--------------+------------
443 199 BC | -198 |
444 ... | ... | 100s BC (100 years)
445 100 BC | -99 |
446 ----------+--------------+------------
447 99 BC | -98 |
448 ... | ... | 0s BC (only 99 years)
449 1 BC | 0 |
450 ----------+--------------+------------
451 1 | 1 |
452 ... | ... | 0s (only 99 years)
453 99 | 99 |
454 ----------+--------------+------------
455 100 | 100 |
456 .. | .. | 100s (100 years)
457 199 | 199 |
458 ----------+--------------+------------
459 200 | 200 | 200s (100 years)
460 .. | .. |
461 """
462
463 - def label(self, time, major=False):
464 if major:
465 coptic_time = CopticDateTime.from_time(time)
466 return self._format_century(
467 self._century_number(
468 self._century_start_year(coptic_time.year)
469 ),
470 coptic_time.is_bc()
471 )
472 else:
473 return ""
474
481
487
489 if century_start_year > 99:
490 return century_start_year
491 elif century_start_year >= -98:
492 return 0
493 else:
494 return self._century_number(-century_start_year - 98)
495
497 return start_year + self._century_year_len(start_year)
498
500 if start_year in [-98, 1]:
501 return 99
502 else:
503 return 100
504
510
512 if year > 99:
513 return year - int(year) % 100
514 elif year >= 1:
515 return 1
516 elif year >= -98:
517 return -98
518 else:
519 return -self._century_start_year(-year + 1) - 98
520
523
524 """
525 Year Name | Year integer | Decade name
526 ----------+--------------+------------
527 .. | .. |
528 20 BC | -19 | 20s BC (10 years)
529 ----------+--------------+------------
530 19 BC | -18 |
531 18 BC | -17 |
532 17 BC | -16 |
533 16 BC | -15 |
534 15 BC | -14 | 10s BC (10 years)
535 14 BC | -13 |
536 13 BC | -12 |
537 12 BC | -11 |
538 11 BC | -10 |
539 10 BC | -9 |
540 ----------+--------------+------------
541 9 BC | -8 |
542 8 BC | -7 |
543 7 BC | -6 |
544 6 BC | -5 |
545 5 BC | -4 | 0s BC (only 9 years)
546 4 BC | -3 |
547 3 BC | -2 |
548 2 BC | -1 |
549 1 BC | 0 |
550 ----------+--------------+------------
551 1 | 1 |
552 2 | 2 |
553 3 | 3 |
554 4 | 4 |
555 5 | 5 | 0s (only 9 years)
556 6 | 6 |
557 7 | 7 |
558 8 | 8 |
559 9 | 9 |
560 ----------+--------------+------------
561 10 | 10 |
562 11 | 11 |
563 12 | 12 |
564 13 | 13 |
565 14 | 14 |
566 15 | 15 | 10s (10 years)
567 16 | 16 |
568 17 | 17 |
569 18 | 18 |
570 19 | 19 |
571 ----------+--------------+------------
572 20 | 20 | 20s (10 years)
573 .. | .. |
574 """
575
577 self.skip_s_in_decade_text = False
578
579 - def label(self, time, major=False):
580 coptic_time = CopticDateTime.from_time(time)
581 return self._format_decade(
582 self._decade_number(self._decade_start_year(coptic_time.year)),
583 coptic_time.is_bc()
584 )
585
592
598
600 self.skip_s_in_decade_text = value
601
611
613 if year > 9:
614 return int(year) - (int(year) % 10)
615 elif year >= 1:
616 return 1
617 elif year >= -8:
618 return -8
619 else:
620 return -self._decade_start_year(-year + 1) - 8
621
623 return start_year + self._decade_year_len(start_year)
624
626 if self._decade_number(start_year) == 0:
627 return 9
628 else:
629 return 10
630
632 if start_year > 9:
633 return start_year
634 elif start_year >= -8:
635 return 0
636 else:
637 return self._decade_number(-start_year - 8)
638
641
642 - def label(self, time, major=False):
644
649
653
656
657 - def label(self, time, major=False):
663
671
676
679
680 - def label(self, time, major=False):
687
695
698
701
704
708
709 - def label(self, time, major=False):
725
727 start = CopticDateTime.from_time(start)
728 end = CopticDateTime.from_time(end)
729 if start.year == end.year:
730 if start.month == end.month:
731 return "%s-%s %s %s" % (start.day, end.day,
732 abbreviated_name_of_month(start.month),
733 format_year(start.year))
734 return "%s %s-%s %s %s" % (start.day,
735 abbreviated_name_of_month(start.month),
736 end.day,
737 abbreviated_name_of_month(end.month),
738 format_year(start.year))
739 return "%s %s %s-%s %s %s" % (start.day,
740 abbreviated_name_of_month(start.month),
741 format_year(start.year),
742 end.day,
743 abbreviated_name_of_month(end.month),
744 format_year(end.year))
745
753
756
759
760 - def label(self, time, major=False):
770
775
778
781
784
785 - def label(self, time, major=False):
791
795
798
801
802 - def label(self, time, major=False):
808
812
815
822
829
836
839 def move_time(time):
840 coptic_time = CopticDateTime.from_time(time)
841 new_month = coptic_time.month + num
842 new_year = coptic_time.year
843 while new_month < 1:
844 new_month += 13
845 new_year -= 1
846 while new_month > 13:
847 new_month -= 13
848 new_year += 1
849 return coptic_time.replace(year=new_year, month=new_month).to_time()
850 try:
851 return TimePeriod(
852 move_time(period.start_time),
853 move_time(period.end_time)
854 )
855 except ValueError:
856 return None
857
869
874
877
878 - def __init__(self, name, single_name, value_fn, remainder_fn):
883
884 @property
887
888 @property
890 return self._single_name
891
892 @property
894 return self._value_fn
895
896 @property
897 - def remainder_fn(self):
898 return self._remainder_fn
899
900
901 YEARS = DurationType(_('years'), _('year'),
902 lambda ds: ds[0] // 365,
903 lambda ds: (ds[0] % 365, ds[1]))
904 MONTHS = DurationType(_('months'), _('month'),
905 lambda ds: ds[0] // 30,
906 lambda ds: (ds[0] % 30, ds[1]))
907 WEEKS = DurationType(_('weeks'), _('week'),
908 lambda ds: ds[0] // 7,
909 lambda ds: (ds[0] % 7, ds[1]))
910 DAYS = DurationType(_('days'), _('day'),
911 lambda ds: ds[0],
912 lambda ds: (0, ds[1]))
913 HOURS = DurationType(_('hours'), _('hour'),
914 lambda ds: ds[0] * 24 + ds[1] // 3600,
915 lambda ds: (0, ds[1] % 3600))
916 MINUTES = DurationType(_('minutes'), _('minute'),
917 lambda ds: ds[0] * 1440 + ds[1] // 60,
918 lambda ds: (0, ds[1] % 60))
919 SECONDS = DurationType(_('seconds'), _('second'),
920 lambda ds: ds[0] * 86400 + ds[1],
921 lambda ds: (0, 0))
969