mhc 1.2.3 → 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/mhc/converter.rb CHANGED
@@ -131,15 +131,86 @@ module Mhc
131
131
  end
132
132
  end
133
133
 
134
+ # https://github.com/rubyredrick/ri_cal
135
+ def value_part(unit, diff) # :nodoc:
136
+ (diff == 0) ? nil : "#{diff}#{unit}"
137
+ end
138
+
139
+ # https://github.com/rubyredrick/ri_cal
140
+ def from_datetimes(start, finish, sign = '') # :nodoc:
141
+ if start > finish
142
+ from_datetimes(finish, start, '-')
143
+ else
144
+ diff = finish - start
145
+ days_diff = diff.to_i
146
+ hours = (diff - days_diff) * 24
147
+ hour_diff = hours.to_i
148
+ minutes = (hours - hour_diff) * 60
149
+ min_diff = minutes.to_i
150
+ seconds = (minutes - min_diff) * 60
151
+ sec_diff = seconds.to_i
152
+
153
+ day_part = value_part('D',days_diff)
154
+ hour_part = value_part('H', hour_diff)
155
+ min_part = value_part('M', min_diff)
156
+ sec_part = value_part('S', sec_diff)
157
+ t_part = (hour_diff.abs + min_diff.abs + sec_diff.abs) == 0 ? "" : "T"
158
+ "P#{day_part}#{t_part}#{hour_part}#{min_part}#{sec_part}"
159
+ end
160
+ end
161
+
162
+ # Convert ~X-SC-Days:~ to RFC5545 3.8.2 ~RDATE~
163
+ #
164
+ # RDATE allows three types of format: PERIOD, DATE, DATE-TIME.
165
+ # + DATE :: 20140301
166
+ # + DATE-TIME :: 20140301T123000
167
+ # + PERIOD :: 20140301T123000/20140301T143000 or 20140301T123000/PT2H
168
+ #
169
+ # NOTE: *Google calenadr does not accept PERIOD*
170
+ # That's why we cannot make X-SC-Day: have different duration-period for each occurrence.
171
+ #
134
172
  def rdates(event)
135
173
  return nil if event.dates.empty?
136
- ocs = Mhc::OccurrenceEnumerator.new(event, event.dates, empty_dates, empty_condition, empty_duration).map {|oc| oc.dtstart}
174
+ # Get all RDATE candidates from X-SC-Date
175
+ ocs = Mhc::OccurrenceEnumerator.new(event, event.dates, empty_dates, empty_condition, empty_duration).map do |oc|
176
+ if oc.dtstart.respond_to?(:hour)
177
+ # duration = from_datetimes(oc.dtstart, oc.dtend)
178
+
179
+ # 20140301T123000/20140301T143000
180
+ dtstart = IcalendarImporter.tz_convert(oc.dtstart, dst_tzid: 'UTC').strftime("%Y%m%dT%H%M00Z")
181
+ dtend = IcalendarImporter.tz_convert(oc.dtend, dst_tzid: 'UTC').strftime("%Y%m%dT%H%M00Z")
182
+
183
+ dtstart + "/" + dtend
184
+ # dtstart + "/" + duration
185
+ else
186
+ oc.dtstart
187
+ end
188
+ end
189
+
190
+ # Check if all in X-SC-Date should be converted into RDATE,
191
+ # because the first occurrence of X-SC-Date might be dedicated
192
+ # to DTSTART in some particular case.
193
+ #
137
194
  if event.recurring?
195
+ # Use all values of X-SC-Date as RDATE, because DTSTART
196
+ # should be calculated from recurrence-rule (X-SC-Cond and
197
+ # X-SC-Duration).
138
198
  ocs
139
199
  else
140
- ocs = ocs[1..-1]
141
- return nil if ocs.empty?
200
+ # This is Workaround for avoiding the serious bug in Android.
201
+ # Android badly ignores DTSTART-DTEND if RDATE is set.
202
+ # As a result, the first occurence is vanished.
203
+ # So, I set the first occurence twice; in RDATE and DTSTART.
204
+ return nil if ocs[1..-1].empty?
142
205
  return ocs
206
+
207
+ # This is what I wanted to do:
208
+ # Remove the first occurence of X-SC-Date, because the first
209
+ # value should be dedicated to DTSTART.
210
+ #
211
+ # ocs = ocs[1..-1]
212
+ # return nil if ocs.empty?
213
+ # return ocs
143
214
  end
144
215
  end
145
216
 
data/lib/mhc/datastore.rb CHANGED
@@ -25,7 +25,7 @@ module Mhc
25
25
  Dir.foreach(".") do |ent|
26
26
  parse_mhcc(ent).each {|ev|
27
27
  next if category && !ev.in_category?(category)
28
- next if recurrence && !ev.in_recurrence?(recurrence)
28
+ next if recurrence && !(ev.recurrence_tag.to_s == recurrence)
29
29
  yielder << ev
30
30
  } if /\.mhcc$/ =~ ent
31
31
  next unless /\.mhc$/ =~ ent
@@ -52,22 +52,25 @@ module Mhc
52
52
  return Event.parse_file(path)
53
53
  end
54
54
 
55
- def create(event)
55
+ def create(event, draft = false)
56
56
  if find_by_uid(event.uid)
57
57
  raise "Already exist uid:#{uid} in #{@basedir}"
58
58
  end
59
+ path = uid_to_path(event.uid, draft)
59
60
  File.open(path, "w") do |f|
60
61
  f.write(event.dump)
61
62
  end
63
+ return path.to_s
62
64
  end
63
65
 
64
- def update(event)
65
- unless path = uid_to_path(event.uid)
66
+ def update(event, draft = false)
67
+ unless path = uid_to_path(event.uid, draft)
66
68
  raise "Not found uid:#{uid} in #{@basedir}"
67
69
  end
68
70
  File.open(path, "w") do |f|
69
71
  f.write(event.dump)
70
72
  end
73
+ return path.to_s
71
74
  end
72
75
 
73
76
  def delete(uid_or_event)
@@ -105,7 +108,8 @@ module Mhc
105
108
  return Dir.glob(glob).first
106
109
  end
107
110
 
108
- def uid_to_path(uid)
111
+ def uid_to_path(uid, draft = false)
112
+ return @basedir + ('draft/' + uid + '.mhc') if draft
109
113
  return @basedir + ('spool/' + uid + '.mhc')
110
114
  end
111
115
 
@@ -0,0 +1,32 @@
1
+ module Mhc
2
+ class Formatter
3
+ class Html < Base
4
+ TEMPLATE_DIR = File.expand_path("../../templates", __FILE__)
5
+
6
+ def initialize(date_range:, options:)
7
+ super(date_range: date_range, options: options)
8
+ @json_formatter = Json.new(date_range: date_range, options: options)
9
+ end
10
+
11
+ def <<(occurrence)
12
+ @json_formatter << occurrence
13
+ end
14
+
15
+ private
16
+
17
+ def format_header(context)
18
+ require "erb"
19
+ template_path = File.expand_path("full-calendar.html.erb", TEMPLATE_DIR)
20
+ @template = ERB.new(File.open(template_path).read, nil, "-")
21
+ return ""
22
+ end
23
+
24
+ def format_body(context)
25
+ env = Struct.new(:json_event_array, :tzid)
26
+ mhc = env.new(@json_formatter.to_s, Mhc.default_tzid) # used in ERB template
27
+ @template.result(binding)
28
+ end
29
+
30
+ end # class Html
31
+ end # class Formatter
32
+ end # module Mhc
data/lib/mhc/formatter.rb CHANGED
@@ -21,6 +21,8 @@ module Mhc
21
21
  Howm.new(date_range: date_range, options:options)
22
22
  when :json
23
23
  Json.new(date_range: date_range, options:options)
24
+ when :html
25
+ Html.new(date_range: date_range, options:options)
24
26
  else
25
27
  raise Formatter::NameError.new("Unknown format: #{formatter} (#{formatter.class})")
26
28
  end
@@ -37,6 +39,7 @@ module Mhc
37
39
  autoload :OrgTable, "#{dir}/org_table.rb"
38
40
  autoload :SymbolicExpression, "#{dir}/symbolic_expression.rb"
39
41
  autoload :Text, "#{dir}/text.rb"
42
+ autoload :Html, "#{dir}/html.rb"
40
43
 
41
44
  end # class Formatter
42
45
  end # module Mhc
@@ -0,0 +1,417 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+
8
+ <title>Calendar</title>
9
+
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.css" />
11
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
12
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" />
13
+
14
+ <style media="screen" type="text/css">
15
+ .container {
16
+ // max-width: 100%;
17
+ width: auto;
18
+ }
19
+
20
+ .ui-draggable {
21
+ cursor: grab;
22
+ }
23
+
24
+ a {
25
+ cursor: pointer;
26
+ }
27
+
28
+ .fc-sun {
29
+ color:#gray;
30
+ background-color: #fff0f0;
31
+ }
32
+
33
+ .fc-sat {
34
+ color:#gray;
35
+ background-color: #f0f0ff;
36
+ }
37
+
38
+
39
+
40
+ #calendar .mhc-allday {
41
+ background-color: lightblue;
42
+ border-color: lightblue;
43
+ color: black;
44
+ }
45
+
46
+ #calendar .mhc-time-range {
47
+ background-color: #f7f7ff;
48
+ border-color: #f7f7ff;
49
+ color: black;
50
+ }
51
+
52
+ #calendar .mhc-time-range:hover {
53
+ background-color: aliceblue;
54
+ border-color: lavender;
55
+ color: black;
56
+ }
57
+
58
+ #calendar .mhc-category-holiday {
59
+ background-color: orangered;
60
+ border-color: orangered;
61
+ color: white;
62
+ }
63
+
64
+ #calendar .mhc-category-birthday {
65
+ background-color: #ffffe8;
66
+ border-color: #ffffe8;
67
+ color: black;
68
+ }
69
+
70
+
71
+
72
+
73
+ #side-calendar .mhc-category-birthday {
74
+ display: none;
75
+ }
76
+
77
+
78
+
79
+
80
+ #stuck-events .fc-list-heading {
81
+ display: none;
82
+ }
83
+
84
+ </style>
85
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
86
+ <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
87
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.js"></script>
88
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script>
89
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.js"></script>
90
+
91
+ </head>
92
+ <body>
93
+ <!--
94
+ <div class="navmenu navmenu-default navmenu-fixed-left offcanvas">
95
+ <a class="navmenu-brand" href="#">brand</a>
96
+ <ul class="nav navmenu-nav">
97
+ <li><a href="#">Menu text 1</a></li>
98
+ <li><a href="#">Menu text 2</a></li>
99
+ <li><a href="#">Menu text 3</a></li>
100
+ </ul>
101
+ </div>
102
+ <div class="navbar navbar-default navbar-fixed-top">
103
+ <button type="button" class="navbar-toggle" data-toggle="offcanvas" data-target=".navmenu" data-canvas="body">
104
+ <span class="icon-bar"></span>
105
+ <span class="icon-bar"></span>
106
+ <span class="icon-bar"></span>
107
+ </button>
108
+ </div>
109
+ -->
110
+
111
+ <div class="container">
112
+ <div class="row">
113
+
114
+ <div class="col-xs-3">
115
+ <ul class="nav nav-tabs">
116
+ <li class="active"><a data-toggle="tab" href="#side-calendar">Past Events</a></li>
117
+ <li><a data-toggle="tab" href="#stuck-events">Stuck Events</a></li>
118
+ </ul>
119
+ <div class="tab-content">
120
+ <div id="side-calendar" class="tab-pane fade in active"></div>
121
+ <div id="stuck-events" class="tab-pane fade"></div>
122
+ </div>
123
+ </div><!-- col-xs-3 -->
124
+
125
+ <div class="col-xs-9" id="calendar"></div> <!-- col-xs-9 -->
126
+ </div><!-- row -->
127
+ </div><!-- /.container -->
128
+
129
+ <script>
130
+ function create_uuid() {
131
+ var d = +new Date();
132
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
133
+ .replace(/[xy]/g, function(c) {
134
+ var r = (d + Math.random() * 16) % 16 | 0;
135
+ return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16).toUpperCase();
136
+ });
137
+ }
138
+
139
+ function max_height_for(element) {
140
+ var top = $(element).position().top;
141
+ return $(window).height() - top - 7;
142
+ }
143
+
144
+ function adjust_height(element) {
145
+ var height = max_height_for(element);
146
+ $(element).fullCalendar('option', 'height', height);
147
+ }
148
+
149
+ var json_event_array = [<%= mhc.json_event_array %>];
150
+
151
+ $(document).ready(function() {
152
+
153
+ $('#side-calendar').fullCalendar({
154
+ defaultView: 'listMonth',
155
+ header: {
156
+ left: '',
157
+ center: 'title',
158
+ right: ''
159
+ },
160
+ height: max_height_for('#side-calendar'),
161
+ editable: true,
162
+ eventResourceEditable: true,
163
+ eventLimit: true,
164
+ selectable: true,
165
+ droppable: true,
166
+ timezone: '<%= mhc.tzid %>',
167
+ timeFormat: "HH:mm",
168
+ displayEventEnd: false,
169
+ allDayText: "",
170
+ month: 'HH:mm',
171
+ week: 'HH:mm',
172
+ day: 'HH:mm',
173
+ // eventSources: [<%= $stuck_recurrences_json %>],
174
+ eventSources: json_event_array,
175
+ XeventDragStart: function(calEvent, jsEvent, ui, view) {
176
+ alert('Drag Event: ' + calEvent.title);
177
+ alert('Event ID: ' + calEvent.id);
178
+ alert('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
179
+ alert('View: ' + view.name);
180
+ // change the border color just for fun
181
+ $(this).css('border-color', 'red');
182
+ },
183
+ viewRender: function(view, element) {
184
+ $('tr.fc-list-item').each(function() {
185
+ var duration;
186
+ var seg = $(this).data('fc-seg');
187
+ var myevent = seg.footprint.getEventLegacy();
188
+ if (myevent.end) {
189
+ var minutes = moment.duration(myevent.end.diff(myevent.start)).asMinutes();
190
+ var days = Math.floor(minutes/(24*60));
191
+ minutes -= days * 24 * 60;
192
+ var hours = Math.floor(minutes/60);
193
+ minutes -= hours * 60;
194
+ duration = days + "." + hours + ":" + minutes;
195
+ } else {
196
+ duration = "0.00:00";
197
+ }
198
+ if (myevent.title == "母の日") {
199
+ // alert('My Event: ' + myevent.title);
200
+ // alert('Duration: ' + duration);
201
+ }
202
+ var uuid = create_uuid();
203
+ // alert('Seg: ' + seg);
204
+ $(this).data('event', {
205
+ title: myevent.title,
206
+ allDay: myevent.allDay,
207
+ start: myevent.start.format("HH:mm"),
208
+ duration: duration,
209
+ stick: true,
210
+ className: myevent.className
211
+ });
212
+ });
213
+
214
+ $('tr.fc-list-item').draggable({
215
+ appendTo: "#calendar",
216
+ cursorAt: {top: 5, left: 5},
217
+ iframeFix: true,
218
+ refreshPositions: true,
219
+ scroll: false,
220
+ cursor: "move",
221
+ revert: true, // will cause the event to go back to its
222
+ revertDuration: 0, // original position after the drag
223
+ helper: "clone",
224
+ zIndex: 100,
225
+ opacity: 0.35,
226
+
227
+ start: function(event, ui) {
228
+ }
229
+ });
230
+ if(view.name == 'listMonth') {
231
+ adjust_height('#side-calendar');
232
+ }
233
+ },
234
+ windowResize: function(view) {
235
+ if(view.name == 'listMonth') {
236
+ adjust_height('#side-calendar');
237
+ }
238
+ }
239
+ });
240
+
241
+ $('#stuck-events').fullCalendar({
242
+ defaultView: 'listall',
243
+ Xheader: {
244
+ left: '',
245
+ center: '',
246
+ right: ''
247
+ },
248
+ header: false,
249
+ views: {
250
+ listall: {
251
+ type: 'list',
252
+ duration: { days: 3650},
253
+ dayCount: 30
254
+ }
255
+ },
256
+ height: max_height_for('#side-calendar'), // XXX
257
+ editable: true,
258
+ eventResourceEditable: true,
259
+ eventLimit: true,
260
+ selectable: true,
261
+ droppable: true,
262
+ timezone: '<%= mhc.tzid %>',
263
+ timeFormat: " ",
264
+ allDayText: "",
265
+ month: 'HH:mm',
266
+ week: 'HH:mm',
267
+ day: 'HH:mm',
268
+ eventSources: [<%= $stuck_recurrences_json %>],
269
+ XeventDragStart: function(calEvent, jsEvent, ui, view) {
270
+ alert('Drag Event: ' + calEvent.title);
271
+ alert('Event ID: ' + calEvent.id);
272
+ alert('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
273
+ alert('View: ' + view.name);
274
+ // change the border color just for fun
275
+ $(this).css('border-color', 'red');
276
+ },
277
+ viewRender: function(view, element) {
278
+ $('tr.fc-list-item').each(function() {
279
+ var duration;
280
+ var seg = $(this).data('fc-seg');
281
+ var myevent = seg.footprint.getEventLegacy();
282
+ if (myevent.end) {
283
+ var minutes = moment.duration(myevent.end.diff(myevent.start)).asMinutes();
284
+ var days = Math.floor(minutes/(24*60));
285
+ minutes -= days * 24 * 60;
286
+ var hours = Math.floor(minutes/60);
287
+ minutes -= hours * 60;
288
+ duration = days + "." + hours + ":" + minutes;
289
+ } else {
290
+ duration = "0.00:00";
291
+ }
292
+ if (myevent.title == "母の日") {
293
+ // alert('My Event: ' + myevent.title);
294
+ // alert('Duration: ' + duration);
295
+ }
296
+ var uuid = create_uuid();
297
+ // alert('Seg: ' + seg);
298
+ $(this).data('event', {
299
+ title: myevent.title,
300
+ allDay: myevent.allDay,
301
+ start: myevent.start.format("HH:mm"),
302
+ duration: duration,
303
+ stick: true,
304
+ className: myevent.className
305
+ });
306
+ });
307
+
308
+ $('tr.fc-list-item').draggable({
309
+ appendTo: "#calendar",
310
+ cursorAt: {top: 5, left: 5},
311
+ iframeFix: true,
312
+ refreshPositions: true,
313
+ scroll: false,
314
+ cursor: "move",
315
+ revert: true, // will cause the event to go back to its
316
+ revertDuration: 0, // original position after the drag
317
+ helper: "clone",
318
+ zIndex: 100,
319
+ opacity: 0.35,
320
+
321
+ start: function(event, ui) {
322
+ }
323
+ });
324
+ if(view.name == 'listMonth') {
325
+ adjust_height('#stuck-events');
326
+ }
327
+ },
328
+ windowResize: function(view) {
329
+ if(view.name == 'listMonth') {
330
+ adjust_height('#stuck-events');
331
+ }
332
+ }
333
+ });
334
+
335
+ $('#calendar').fullCalendar({
336
+ header: {
337
+ left: 'prev,next today',
338
+ center: 'title',
339
+ right: 'month,agendaWeek,agendaDay,listMonth'
340
+ },
341
+ firstDay: 1,
342
+ height: max_height_for('#calendar'),
343
+ editable: true,
344
+ eventResourceEditable: true,
345
+ eventLimit: true,
346
+ selectable: true,
347
+ droppable: true,
348
+
349
+ // drop: Event ではない draggable からドロップされたとき.
350
+ // draggable が event として認識できないようなときでも発火する
351
+ drop: function(date) {
352
+ // alert("Dropped on " + date.format());
353
+ },
354
+
355
+ // eventReceive: Event ではない draggable からドロップされたとき
356
+ // draggable が event として認識可能な property を持っている場合だけ発火する
357
+ eventReceive: function(event) {
358
+ event.id = create_uuid(); // XXX! これがうまくいかない
359
+ $('#calendar').fullCalendar('updateEvent', event);
360
+ // alert("Drop event from ourter world! ID: " + event.id);
361
+ },
362
+
363
+ // eventDrop: 既に登録されている event を変更したとき
364
+ eventDrop: function(event, delta, revertFunc, jsEvent, ui, view) {
365
+ // alert("eventDrop:" + event.title);
366
+ // alert("eventDrop:" + event.id);
367
+ },
368
+
369
+ // return (this.eventInstance || this.eventDef).toLegacy()
370
+ eventClick: function(calEvent, jsEvent, view) {
371
+ var yesno = prompt('Do you delete ' + calEvent.title + '?');
372
+ // alert('Event ID: ' + calEvent.id);
373
+ if (yesno == "yes"){
374
+ $('#calendar').fullCalendar('removeEvents', [calEvent.id]);
375
+ }
376
+ // alert('This Event: ' + $(this).getEventLegacy().title);
377
+ //alert('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
378
+ //alert('View: ' + view.name);
379
+ // change the border color just for fun
380
+ // $(this).css('border-color', 'red');
381
+ },
382
+
383
+ timezone: '<%= mhc.tzid %>',
384
+ timeFormat: "HH:mm",
385
+ allDayText: "",
386
+ month: 'HH:mm',
387
+ week: 'HH:mm',
388
+ day: 'HH:mm',
389
+ eventSources: json_event_array,
390
+ // eventSources: [<%= mhc.json_event_array %>],
391
+ viewRender: function(view, element) {
392
+ if(view.name == 'month') {
393
+ adjust_height('#calendar');
394
+ adjust_height('#stuck-events');
395
+ }
396
+ var currentDate = $('#calendar').fullCalendar('getDate');
397
+ // alert("The current date of the calendar is " + currentDate.format());
398
+ $('#side-calendar').fullCalendar('gotoDate', currentDate.subtract(1, 'y'));
399
+ $('#stuck-events').fullCalendar('gotoDate', currentDate.subtract(5, 'y'));
400
+ },
401
+ windowResize: function(view) {
402
+ if(view.name == 'month') {
403
+ adjust_height('#calendar');
404
+ adjust_height('#stuck-events');
405
+ }
406
+ }
407
+ }) // $('#calendar')
408
+
409
+ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
410
+ var target = $(e.target).attr("href") // activated tab
411
+ adjust_height(target);
412
+ });
413
+
414
+ });
415
+ </script>
416
+ </body>
417
+ </html>
data/lib/mhc/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Mhc
2
- VERSION = "1.2.3"
2
+ VERSION = "1.2.5"
3
3
  PRODID = "-//Quickhack.net//MHC #{Mhc::VERSION}//EN"
4
4
  end
data/mhc.gemspec CHANGED
@@ -23,7 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
24
  spec.require_paths = ["lib"]
25
25
 
26
- spec.add_runtime_dependency "thor", ">= 0.19.1"
26
+ spec.add_runtime_dependency "thor", ">= 1.2.0"
27
+ spec.add_runtime_dependency "rexml", ">= 3.2.4"
27
28
  spec.add_runtime_dependency "ri_cal", ">= 0.8.8"
28
29
  spec.add_runtime_dependency "tzinfo", ">= 1.2.2"
29
30
  spec.add_runtime_dependency "tzinfo-data", ">= 1.2015.4"
@@ -31,14 +31,14 @@ X-SC-Record-Id: AC1B378C-BAFE-4B6E-AF9C-78C2377E8AA4
31
31
  X-SC-Subject: 天皇誕生日
32
32
  X-SC-Category: Holiday Japanese
33
33
  X-SC-Cond: 29 Apr
34
- X-SC-Duration: 19480429-19980429
34
+ X-SC-Duration: 19490429-19880429
35
35
  X-SC-Record-Id: B78EAAEE-9963-4573-9EC7-0879F8940AEE
36
36
 
37
37
  X-SC-Subject: みどりの日
38
38
  X-SC-Category: Holiday Japanese
39
39
  X-SC-Cond: 29 Apr
40
40
  X-SC-Duration: 19890429-20060429
41
- X-SC-Record-Id: B78EAAEE-9963-4573-9EC7-0879F8940AEE
41
+ X-SC-Record-Id: 8C05BF80-006C-4FA7-8CF1-5F1C18CB8641
42
42
 
43
43
  X-SC-Subject: 昭和の日
44
44
  X-SC-Category: Holiday Japanese
@@ -72,14 +72,14 @@ X-SC-Record-Id: 5E03776A-4280-4337-85C0-F1322A3AAE6E
72
72
 
73
73
  X-SC-Subject: 海の日
74
74
  X-SC-Category: Holiday Japanese
75
- X-SC-Day: !20200720 20200723
75
+ X-SC-Day: !20200720 20200723 !20210719 20210722
76
76
  X-SC-Cond: 3rd Mon Jul
77
77
  X-SC-Duration: 20030701-
78
78
  X-SC-Record-Id: BD4156C2-5546-4146-8297-09CF4210A346
79
79
 
80
80
  X-SC-Subject: 山の日
81
81
  X-SC-Category: Holiday Japanese
82
- X-SC-Day: 20200810 !20200811
82
+ X-SC-Day: 20200810 !20200811 20210808 !20210811
83
83
  X-SC-Cond: 11 Aug
84
84
  X-SC-Duration: 20160811-
85
85
  X-SC-Record-Id: FC7C481B-7BF5-4639-B700-3B60CB99E05D
@@ -110,7 +110,7 @@ X-SC-Record-Id: C17D9CA5-28AF-4826-AD33-8B75473E5B52
110
110
 
111
111
  X-SC-Subject: スポーツの日
112
112
  X-SC-Category: Holiday Japanese
113
- X-SC-Day: 20200724 !20201012
113
+ X-SC-Day: 20200724 !20201012 20210723 !20211011
114
114
  X-SC-Cond: 2nd Mon Oct
115
115
  X-SC-Duration: 20200101-
116
116
  X-SC-Record-Id: F10B2B18-B0FB-477E-A7D3-A067B31F4736
@@ -184,13 +184,14 @@ X-SC-Day: 19730430 19730924 19740506 19740916 19741104 19751124
184
184
  20081124 20090506 20100322 20120102 20120430 20121224 20130506
185
185
  20131104 20140506 20141124 20150506 20160321 20170102 20180212
186
186
  20180430 20180924 20181224 20190506 20190812 20191104 20200224 20200506
187
+ 20210809
187
188
  20230102 20240212 20240506 20240812 20240923 20241104 20250224 20250506
188
- 20251124 20260506 20270322 20290212 20290430 20290924 20291224
189
+ 20251124 20260506 20270322 20290212 20290430 20290924
189
190
  20300506 20300812 20301104 20310224 20310506 20311124 20330321 20340102
190
- 20350212 20350430 20350924 20351224 20360506 20361124 20370506
191
- 20400102 20400430 20401224 20410506 20410812 20411104 20420224 20420506
191
+ 20350212 20350430 20350924 20360506 20361124 20370506
192
+ 20400102 20400430 20410506 20410812 20411104 20420224 20420506
192
193
  20421124 20430506 20440321 20450102 20460212 20460430 20460924
193
- 20461224 20470506 20470812 20471104 20480224 20480506 20500321
194
+ 20470506 20470812 20471104 20480224 20480506 20500321
194
195
  X-SC-Category: Holiday Japanese
195
196
  X-SC-Record-Id: E2D696DF-EB49-44D7-B06C-812B10BD99A2
196
197