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.pharaonic.pharaonic import PharaonicDateTime,\
24 julian_day_to_pharaonic_ymd
25 from timelinelib.calendar.pharaonic.monthnames import abbreviated_name_of_month
26 from timelinelib.calendar.pharaonic.time import PharaonicDelta
27 from timelinelib.calendar.pharaonic.time import PharaonicTime
28 from timelinelib.calendar.pharaonic.time import SECONDS_IN_DAY
29 from timelinelib.calendar.pharaonic.weekdaynames import abbreviated_name_of_weekday
30 from timelinelib.calendar.timetype import TimeType
31 from timelinelib.canvas.data import TimeOutOfRangeLeftError
32 from timelinelib.canvas.data import TimeOutOfRangeRightError
33 from timelinelib.canvas.data import TimePeriod
34 from timelinelib.canvas.data import time_period_center
35 from timelinelib.canvas.drawing.interface import Strip
36 from timelinelib.calendar.gregorian.gregorian import gregorian_ymd_to_julian_day
37 from timelinelib.calendar.pharaonic.pharaonic import julian_day_to_pharaonic_ymd
38
39
40 BC = _("BC")
44
47
50
52 match = re.search(r"^(-?\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$", time_string)
53 if match:
54 year = int(match.group(1))
55 month = int(match.group(2))
56 day = int(match.group(3))
57 hour = int(match.group(4))
58 minute = int(match.group(5))
59 second = int(match.group(6))
60 try:
61 return PharaonicDateTime(year, month, day, hour, minute, second).to_time()
62 except ValueError:
63 raise ValueError("Invalid time, time string = '%s'" % time_string)
64 else:
65 raise ValueError("Time not on correct format = '%s'" % time_string)
66
68 return [
69 (_("Go to &Today") + "\tCtrl+T", go_to_today_fn),
70 (_("Go to &Date...") + "\tCtrl+G", go_to_date_fn),
71 ("SEP", None),
72 (_("Backward") + "\tPgUp", backward_fn),
73 (_("Forward") + "\tPgDn", forward_fn),
74 (_("Forward One Wee&k") + "\tCtrl+K", forward_one_week_fn),
75 (_("Back One &Week") + "\tCtrl+W", backward_one_week_fn),
76 (_("Forward One Mont&h") + "\tCtrl+H", forward_one_month_fn),
77 (_("Back One &Month") + "\tCtrl+M", backward_one_month_fn),
78 (_("Forward One Yea&r") + "\tCtrl+R", forward_one_year_fn),
79 (_("Back One &Year") + "\tCtrl+Y", backward_one_year_fn),
80 ("SEP", None),
81 (_("Fit Millennium"), fit_millennium_fn),
82 (_("Fit Century"), create_strip_fitter(StripCentury)),
83 (_("Fit Decade"), create_strip_fitter(StripDecade)),
84 (_("Fit Year"), create_strip_fitter(StripYear)),
85 (_("Fit Month"), create_strip_fitter(StripMonth)),
86 (_("Fit Week"), fit_week_fn),
87 (_("Fit Day"), create_strip_fitter(StripDay)),
88 ]
89
94
95 def label_without_time(time):
96 pharaonic_datetime = PharaonicDateTime.from_time(time)
97 return u"%s %s %s" % (
98 pharaonic_datetime.day,
99 abbreviated_name_of_month(pharaonic_datetime.month),
100 format_year(pharaonic_datetime.year)
101 )
102
103 def time_label(time):
104 return "%02d:%02d" % time.get_time_of_day()[:-1]
105 if time_period.is_period():
106 if has_nonzero_time(time_period):
107 label = u"%s to %s" % (label_with_time(time_period.start_time),
108 label_with_time(time_period.end_time))
109 else:
110 label = u"%s to %s" % (label_without_time(time_period.start_time),
111 label_without_time(time_period.end_time))
112 else:
113 if has_nonzero_time(time_period):
114 label = u"%s" % label_with_time(time_period.start_time)
115 else:
116 label = u"%s" % label_without_time(time_period.start_time)
117 return label
118
124
127
130
132 """
133 Return a tuple (major_strip, minor_strip) for current time period and
134 window size.
135 """
136 day_period = TimePeriod(PharaonicTime(0, 0),PharaonicTime(1, 0))
137 one_day_width = metrics.calc_exact_width(day_period)
138 if one_day_width > 20000:
139 return (StripHour(), StripMinute())
140 elif one_day_width > 600:
141 return (StripDay(), StripHour())
142 elif one_day_width > 45:
143 return (StripWeek(appearance), StripWeekday())
144 elif one_day_width > 25:
145 return (StripMonth(), StripDay())
146 elif one_day_width > 1.5:
147 return (StripYear(), StripMonth())
148 elif one_day_width > 0.12:
149 return (StripDecade(), StripYear())
150 elif one_day_width > 0.012:
151 return (StripCentury(), StripDecade())
152 else:
153 return (StripCentury(), StripCentury())
154
157
160
163
177
180
183
191
194
195 """TO DO: the last day of the month, not week, are considered weekends in the pharaonic calendar. Currently the last two days of the week are considered weekends.
196 """
200
202 return time.julian_day % 10
203
207
211
215
216
217 -def go_to_date_fn(main_frame, current_period, navigation_fn):
218 def navigate_to(time):
219 navigation_fn(lambda tp: tp.center(time))
220 main_frame.display_time_editor_dialog(
221 PharaonicTimeType(), current_period.mean_time(), navigate_to, _("Go to Date"))
222
223
224 -def backward_fn(main_frame, current_period, navigation_fn):
225 _move_page_smart(current_period, navigation_fn, -1)
226
227
228 -def forward_fn(main_frame, current_period, navigation_fn):
229 _move_page_smart(current_period, navigation_fn, 1)
230
231
232 -def _move_page_smart(current_period, navigation_fn, direction):
233 if _whole_number_of_years(current_period):
234 _move_page_years(current_period, navigation_fn, direction)
235 elif _whole_number_of_months(current_period):
236 _move_page_months(current_period, navigation_fn, direction)
237 else:
238 navigation_fn(lambda tp: tp.move_delta(direction * current_period.delta()))
239
260
261
262 -def _move_page_years(curret_period, navigation_fn, direction):
263 def navigate(tp):
264 year_delta = direction * _calculate_year_diff(curret_period)
265 pharaonic_start = PharaonicDateTime.from_time(curret_period.start_time)
266 pharaonic_end = PharaonicDateTime.from_time(curret_period.end_time)
267 new_start_year = pharaonic_start.year + year_delta
268 new_end_year = pharaonic_end.year + year_delta
269 try:
270 new_start = pharaonic_start.replace(year=new_start_year).to_time()
271 new_end = pharaonic_end.replace(year=new_end_year).to_time()
272 if new_end > PharaonicTimeType().get_max_time():
273 raise ValueError()
274 if new_start < PharaonicTimeType().get_min_time():
275 raise ValueError()
276 except ValueError:
277 if direction < 0:
278 raise TimeOutOfRangeLeftError()
279 else:
280 raise TimeOutOfRangeRightError()
281 return tp.update(new_start, new_end)
282 navigation_fn(navigate)
283
288
291
292 """
293 >>> from timelinelib.test.utils import gregorian_period
294
295 >>> _whole_number_of_months(gregorian_period("24 May 490", "23 Jun 490"))
296 True
297
298 >>> _whole_number_of_months(gregorian_period("16 Aug 1", "21 Aug 1 "))
299 True
300
301 >>> _whole_number_of_months(gregorian_period("2 Jan 2013", "2 Mar 2014"))
302 False
303
304 >>> _whole_number_of_months(gregorian_period("1 Jan 2013 12:00", "1 Mar 2014"))
305 False
306 """
307 start, end = PharaonicDateTime.from_time(period.start_time), PharaonicDateTime.from_time(period.end_time)
308 start_months = start.year * 13 + start.month
309 end_months = end.year * 13 + end.month
310 month_diff = end_months - start_months
311
312 return (start.is_first_of_month() and
313 end.is_first_of_month() and
314 month_diff > 0)
315
316
317 -def _move_page_months(curret_period, navigation_fn, direction):
318 def navigate(tp):
319 start = PharaonicDateTime.from_time(curret_period.start_time)
320 end = PharaonicDateTime.from_time(curret_period.end_time)
321 start_months = start.year * 13 + start.month
322 end_months = end.year * 13 + end.month
323 month_diff = end_months - start_months
324 month_delta = month_diff * direction
325 new_start_year, new_start_month = _months_to_year_and_month(start_months + month_delta)
326 new_end_year, new_end_month = _months_to_year_and_month(end_months + month_delta)
327 try:
328 new_start = start.replace(year=new_start_year, month=new_start_month)
329 new_end = end.replace(year=new_end_year, month=new_end_month)
330 start = new_start.to_time()
331 end = new_end.to_time()
332 if end > PharaonicTimeType().get_max_time():
333 raise ValueError()
334 if start < PharaonicTimeType().get_min_time():
335 raise ValueError()
336 except ValueError:
337 if direction < 0:
338 raise TimeOutOfRangeLeftError()
339 else:
340 raise TimeOutOfRangeRightError()
341 return tp.update(start, end)
342 navigation_fn(navigate)
343
346 years = int(months / 13)
347 month = months - years * 13
348 if month == 0:
349 month = 13
350 years -= 1
351 return years, month
352
357
362
375
379
383
388
393
404
408
412
413
414 -def fit_week_fn(main_frame, current_period, navigation_fn):
423
432 navigation_fn(navigate)
433 return fit
434
437
438 """
439 Year Name | Year integer | Decade name
440 ----------+--------------+------------
441 .. | .. |
442 200 BC | -199 | 200s BC (100 years)
443 ----------+--------------+------------
444 199 BC | -198 |
445 ... | ... | 100s BC (100 years)
446 100 BC | -99 |
447 ----------+--------------+------------
448 99 BC | -98 |
449 ... | ... | 0s BC (only 99 years)
450 1 BC | 0 |
451 ----------+--------------+------------
452 1 | 1 |
453 ... | ... | 0s (only 99 years)
454 99 | 99 |
455 ----------+--------------+------------
456 100 | 100 |
457 .. | .. | 100s (100 years)
458 199 | 199 |
459 ----------+--------------+------------
460 200 | 200 | 200s (100 years)
461 .. | .. |
462 """
463
464 - def label(self, time, major=False):
465 if major:
466 pharaonic_time = PharaonicDateTime.from_time(time)
467 return self._format_century(
468 self._century_number(
469 self._century_start_year(pharaonic_time.year)
470 ),
471 pharaonic_time.is_bc()
472 )
473 else:
474 return ""
475
482
488
490 if century_start_year > 99:
491 return century_start_year
492 elif century_start_year >= -98:
493 return 0
494 else:
495 return self._century_number(-century_start_year - 98)
496
498 return start_year + self._century_year_len(start_year)
499
501 if start_year in [-98, 1]:
502 return 99
503 else:
504 return 100
505
511
513 if year > 99:
514 return year - int(year) % 100
515 elif year >= 1:
516 return 1
517 elif year >= -98:
518 return -98
519 else:
520 return -self._century_start_year(-year + 1) - 98
521
524
525 """
526 Year Name | Year integer | Decade name
527 ----------+--------------+------------
528 .. | .. |
529 20 BC | -19 | 20s BC (10 years)
530 ----------+--------------+------------
531 19 BC | -18 |
532 18 BC | -17 |
533 17 BC | -16 |
534 16 BC | -15 |
535 15 BC | -14 | 10s BC (10 years)
536 14 BC | -13 |
537 13 BC | -12 |
538 12 BC | -11 |
539 11 BC | -10 |
540 10 BC | -9 |
541 ----------+--------------+------------
542 9 BC | -8 |
543 8 BC | -7 |
544 7 BC | -6 |
545 6 BC | -5 |
546 5 BC | -4 | 0s BC (only 9 years)
547 4 BC | -3 |
548 3 BC | -2 |
549 2 BC | -1 |
550 1 BC | 0 |
551 ----------+--------------+------------
552 1 | 1 |
553 2 | 2 |
554 3 | 3 |
555 4 | 4 |
556 5 | 5 | 0s (only 9 years)
557 6 | 6 |
558 7 | 7 |
559 8 | 8 |
560 9 | 9 |
561 ----------+--------------+------------
562 10 | 10 |
563 11 | 11 |
564 12 | 12 |
565 13 | 13 |
566 14 | 14 |
567 15 | 15 | 10s (10 years)
568 16 | 16 |
569 17 | 17 |
570 18 | 18 |
571 19 | 19 |
572 ----------+--------------+------------
573 20 | 20 | 20s (10 years)
574 .. | .. |
575 """
576
578 self.skip_s_in_decade_text = False
579
580 - def label(self, time, major=False):
581 pharaonic_time = PharaonicDateTime.from_time(time)
582 return self._format_decade(
583 self._decade_number(self._decade_start_year(pharaonic_time.year)),
584 pharaonic_time.is_bc()
585 )
586
593
599
601 self.skip_s_in_decade_text = value
602
612
614 if year > 9:
615 return int(year) - (int(year) % 10)
616 elif year >= 1:
617 return 1
618 elif year >= -8:
619 return -8
620 else:
621 return -self._decade_start_year(-year + 1) - 8
622
624 return start_year + self._decade_year_len(start_year)
625
627 if self._decade_number(start_year) == 0:
628 return 9
629 else:
630 return 10
631
633 if start_year > 9:
634 return start_year
635 elif start_year >= -8:
636 return 0
637 else:
638 return self._decade_number(-start_year - 8)
639
642
643 - def label(self, time, major=False):
645
650
654
657
658 - def label(self, time, major=False):
664
672
677
680
681 - def label(self, time, major=False):
688
696
699
702
705
709
710 - def label(self, time, major=False):
726
728 start = PharaonicDateTime.from_time(start)
729 end = PharaonicDateTime.from_time(end)
730 if start.year == end.year:
731 if start.month == end.month:
732 return "%s-%s %s %s" % (start.day, end.day,
733 abbreviated_name_of_month(start.month),
734 format_year(start.year))
735 return "%s %s-%s %s %s" % (start.day,
736 abbreviated_name_of_month(start.month),
737 end.day,
738 abbreviated_name_of_month(end.month),
739 format_year(start.year))
740 return "%s %s %s-%s %s %s" % (start.day,
741 abbreviated_name_of_month(start.month),
742 format_year(start.year),
743 end.day,
744 abbreviated_name_of_month(end.month),
745 format_year(end.year))
746
754
757
760
761 - def label(self, time, major=False):
771
776
779
782
785
786 - def label(self, time, major=False):
792
796
799
802
803 - def label(self, time, major=False):
809
813
816
823
830
837
840 def move_time(time):
841 pharaonic_time = PharaonicDateTime.from_time(time)
842 new_month = pharaonic_time.month + num
843 new_year = pharaonic_time.year
844 while new_month < 1:
845 new_month += 13
846 new_year -= 1
847 while new_month > 13:
848 new_month -= 13
849 new_year += 1
850 return pharaonic_time.replace(year=new_year, month=new_month).to_time()
851 try:
852 return TimePeriod(
853 move_time(period.start_time),
854 move_time(period.end_time)
855 )
856 except ValueError:
857 return None
858
870
875
878
879 - def __init__(self, name, single_name, value_fn, remainder_fn):
884
885 @property
888
889 @property
891 return self._single_name
892
893 @property
895 return self._value_fn
896
897 @property
898 - def remainder_fn(self):
899 return self._remainder_fn
900
901
902 YEARS = DurationType(_('years'), _('year'),
903 lambda ds: ds[0] // 365,
904 lambda ds: (ds[0] % 365, ds[1]))
905 MONTHS = DurationType(_('months'), _('month'),
906 lambda ds: ds[0] // 30,
907 lambda ds: (ds[0] % 30, ds[1]))
908 WEEKS = DurationType(_('weeks'), _('week'),
909 lambda ds: ds[0] // 7,
910 lambda ds: (ds[0] % 7, ds[1]))
911 DAYS = DurationType(_('days'), _('day'),
912 lambda ds: ds[0],
913 lambda ds: (0, ds[1]))
914 HOURS = DurationType(_('hours'), _('hour'),
915 lambda ds: ds[0] * 24 + ds[1] // 3600,
916 lambda ds: (0, ds[1] % 3600))
917 MINUTES = DurationType(_('minutes'), _('minute'),
918 lambda ds: ds[0] * 1440 + ds[1] // 60,
919 lambda ds: (0, ds[1] % 60))
920 SECONDS = DurationType(_('seconds'), _('second'),
921 lambda ds: ds[0] * 86400 + ds[1],
922 lambda ds: (0, 0))
970