我正在尝试使用Data:ICal生成ICal Feed,但有些事件是在没有时间的情况下打印的。我已经读过,如果它是000000,则不需要时间,但Google日历在没有正确时间的情况下无法处理这些事件。
这是一个示例脚本和输出。我需要输出到UTC时区。
#!/usr/bin/perl -w
use strict;
use Date::ICal;
use Data::ICal;
use Data::ICal::Entry::Event;
use DateTime;
use Data::Dumper;
sub get_utc_offset($) {
my ($orig_tz_str) = @_;
# Using a set winter date to avoid problems with daylight savings time
my $utc_compare_datetime = DateTime->new(
year => 2012,
month => 1,
day => 1,
hour => 1,
minute => 1,
time_zone => 'UTC'
);
my $tz = DateTime::TimeZone->new(name => $orig_tz_str);
my $utc_offset = $tz->offset_for_datetime($utc_compare_datetime);
my $utc_offset_str = DateTime::TimeZone->offset_as_string($utc_offset);
return $utc_offset_str;
}
sub add_ical_event($$$$$$) {
my ($calendar, $start, $end, $summary, $description, $timezone) = @_;
my $offset = get_utc_offset($timezone);
$description = 'none' if (!$description);
my $event = Data::ICal::Entry::Event->new();
$event->add_properties(
summary => $summary,
description => $description,
dtstart => Date::ICal->new( ical => $start, offset => $offset )->ical,
dtend => Date::ICal->new( ical => $end, offset => $offset )->ical,
dtstamp => Date::ICal->new( epoch => time )->ical
);
$calendar->add_entry($event);
}
# Tests
# ----------------------------------------------------------------------------
my $timezone = 'America/New_York';
my $calendar = Data::ICal->new();
$calendar->add_properties(
method => "PUBLISH",
prodid => "-//Test Cal//NONSGML Calendar//EN",
'X-WR-CALNAME' => 'Test Cal'
);
my (%events) = (
1 => {
summary => 'Test Shift Tool - Testing Shift',
description => '',
start => '20130828T160000',
end => '20130828T190000',
timezone => $timezone
},
2 => {
summary => 'New Member Meeting',
description => '',
start => '20130722T190000',
end => '20130722T210000',
timezone => $timezone
},
3 => {
summary => 'public',
description => '',
start => '20130630T130000',
end => '20130630T140000',
timezone => $timezone
}
);
foreach my $key (sort keys %events) {
my $e = $events{$key};
add_ical_event(
$calendar,
$e->{start},
$e->{end},
$e->{summary},
$e->{description},
$e->{timezone}
);
}
print $calendar->as_string;
请注意,某些事件的开始日期或结束日期没有时间。当我手动添加T000000Z时,这些事件会正确导入Google日历。关于如何强迫所有活动有时间的任何建议?
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
PRODID:-//Digital Cheetah//NONSGML Calendar//EN
X-WR-CALNAME:Digital Cheetah
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130829Z
DTSTAMP:20130823T214317Z
DTSTART:20130828T210000Z
SUMMARY:Test Shift Tool - Testing Shift
END:VEVENT
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130723T020000Z
DTSTAMP:20130823T214317Z
DTSTART:20130723Z
SUMMARY:New Member Meeting
END:VEVENT
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130630T190000Z
DTSTAMP:20130823T214317Z
DTSTART:20130630T180000Z
SUMMARY:public
END:VEVENT
END:VCALENDAR
答案 0 :(得分:1)
我已经读过,如果它是000000
,则不需要时间
That's not what the RFC says。让我们参考以下部分:
我将引用相关的格式规范,在这里:
date = date-value
date-value = date-fullyear date-month date-mday
date-fullyear = 4DIGIT
date-time = date "T" time ;As specified in the date and time
;value definitions
dtstamp = "DTSTAMP" stmparam ":" date-time CRLF
当您的输出包含DTSTAMP时,ICal规范要求date-time
跟随它。
它将我们带到Date :: ICal及其ical
方法。它会返回iCal date
还是date-time
?事实证明,它会通过检查您的时间戳是否具有000000
的时间来尝试猜测您想要的格式。请参阅line 286 of ICal.pm。
可能是我们期望Data :: ICal :: Entry来处理这种情况。我可能在这方面缺少验证码,但目前我没有看到任何明显相关的东西。看起来它接受属性值而不检查它们。
根据您的观点,这听起来像是一个错误或库的限制。
那么......你应该怎么解决这个问题?理想情况下,这些库中的一个应该检查并处理这种情况。与此同时,你需要重新站起来:
快速而肮脏的修复:如果您的时间为零,则将其提高一秒钟; ical
现在会返回一个有效但稍微不准确的date-time
字符串。
好一点:检查ical
的返回值;如果是date
,请将其重新格式化为date-time
。
在使用之前测试一下,但也许是这样的:
dtstart => $ical =~ s/(\d{8})Z/$1T000000Z/r;