At the Forge - Sunbird 和 iCalendar
当我最初开始编写服务器端软件时,我嘲笑自己正在编写应用程序的想法。毕竟,我只是在编写少量代码;我所做的任何事情都无法与真正在某人计算机桌面上运行的程序相提并论。
当然,自从那些早期日子以来,计算机行业发生了很大的变化。今天,基于 Web 的应用程序不仅是既定事实,而且它们似乎在我们的日常生活中扮演着越来越重要的角色。最近,我开始研究可以用来准备美国所得税的软件。我不应该感到惊讶地发现,许多公司现在都在提供基于 Web 的税务计算程序。ASP,或应用程序服务提供商,这个术语在几年前很热门,当时似乎所有软件都将在 Web 上运行。尽管有一些明显的成功案例,但也存在许多失败案例,原因包括技术和商业方面。
很容易理解为什么基于 Web 的应用程序对企业有吸引力:您不再需要在每个平台上测试您的软件,而只需在少数浏览器上测试即可。您不再需要支持许多不同版本的软件,因为在任何给定时间只有一个版本可访问。错误修复和软件更新几乎可以持续集成到系统中。该软件可以从任何有互联网连接的地方访问,而不仅仅是在安装它的计算机上。这样的例子不胜枚举。从许多角度来看,这种方法比大量生产 CD、在数百种配置上测试软件以及配备大型呼叫中心来支持所有这些配置更有意义。
但是,尽管大肆宣传,但 Web 应用程序与桌面应用程序相比仍然受到限制。由于所有重要的处理都在服务器上完成,包括写入和读取数据库和文件,因此几乎不可能获得来自界面的即时反馈。即使使用最快的服务器和许多巧妙的技巧,这些程序仍然可能显得有些乏味。例如,谷歌的新地图系统(参见在线资源)表明,创建感觉很像桌面应用程序的 Web 应用程序是可能的,尽管很困难。
我们这些没有谷歌资源的人越来越多地转向另一种解决方案,即使用混合软件——严重依赖 Web 技术的桌面应用程序。过去,Web 技术可以相当精确地描述为使用 URL 通过 HTTP 检索的 HTML 格式文档。长期以来,Web 浏览器是唯一认真使用这些标准的程序。
然而,今天,越来越多的桌面程序使用 HTML、HTTP 和 URL,即使它们不是 Web 浏览器。它们使用 URL 来定位远程资源,使用 HTML 因为它是一种简单、普遍理解的创建超链接文档的方法,并使用 HTTP 因为它可靠、简单、通用且可缓存。我不知道有太多文字处理器和电子表格使用这些协议的例子——至少,就我所知——但有一个混合程序在我的生活中扮演着越来越重要的角色,Mozilla Sunbird。
Sunbird(图 1)是可以与 Firefox 或 Thunderbird 一起安装的日历扩展的独立版本。与这两个程序的集成远非完美,我有时希望在没有另一个程序的情况下运行或重启一个程序。因此,我在夏天安装了 Sunbird,并且对每个新版本的发布都感到满意。

图 1. Sunbird 主窗口,多周模式。我的三个日历(Hebcal 2005 和 Northwestern 研究生院)中的两个已进行颜色编码,无论是在定义窗格还是主窗口中。另请注意我的待办事项列表中的项目是如何进行颜色编码的,指示它们是按时、迟到、需要注意还是正在进行中。
现在,您可能会认为日历使用 Web 技术并没有什么内在的用处。但在 Sunbird 和 iCalendar 标准的情况下,有一个主要好处——即能够创建用于公开消费的日历。本月,我们将开始为期数月的基于 iCalendar 标准创建、分发和共享日历的旅程。在此过程中,我们将不仅了解如何使用 iCalendar,还将了解混合应用程序如何提供强大的功能组合和增强的用户体验。
iCalendar 是一种用于在不同计算机之间共享日历信息的互联网标准。基本思想很简单:如果我办公室的每个人都在自己的计算机上跟踪他们的日程安排,这对那些个人来说是高效的,但对于团队来说,并不比每个人都使用袖珍日记更好。安排会议仍然会很麻烦。此外,小组活动必须在每个人的日历上输入一次——这意味着当会议从星期一移到星期三时,团队中的每个人都需要相应地调整他们各自的日历。
iCalendar 的设计目的是通过标准化日历文件本身来解决这个问题,以便这些文件可以在程序之间传输。据我所知,最初的愿景是每个人都在他们的计算机上使用实现 iCalendar 的程序,并通过网络和互联网与他人共享该信息。现实花了一些时间才赶上这一理论,但现在有各种各样的程序可以实现 iCalendar 套件的部分功能。
我应该注意到,整个 iCalendar 项目一直是命名问题不幸的受害者。存储数据并可用于交换信息的文件称为 vCalendar,就像电子名片格式称为 vCard 一样。但是许多人和应用程序,包括 Sunbird,都将文件格式称为 iCalendar,即使该文件本身标识为 vCalendar。您可以想象,术语 iCalendar 已缩短为 iCal,这尤其不幸,因为 Apple 的 Mac OS X 操作系统附带了一个名为 iCal 的程序,该程序使用 vCalendar 文件格式。由于使用 vCalendar 来描述这些文件似乎已经过时,我只是使用 iCalendar 这个词来指代文件格式和整个标准。
下载并安装 Sunbird 独立日历程序的相应版本;有关 URL,请参阅资源。如果您胆子更大,您可以安装其中一个每夜构建版本;我实际上正在使用 Sunbird 作为我的主要日历应用程序,所以我一直在使用官方构建版本。如果您希望将日历集成到 Firefox 或 Thunderbird 中,请转到主下载页面,然后选择您要安装的相应扩展和版本。如果您安装了 Firefox 或 Thunderbird 的扩展,则需要重新启动宿主程序才能继续。
Sunbird 允许您创建两种类型的项目,事件和任务。事件通常显示在日历本身上,可以包括假期和会议。任务通常显示在屏幕的左侧,并指示您应该完成的事情,带有可选的开始和结束日期。Sunbird 根据任务需要完成的紧迫程度更改任务的颜色;逾期任务为红色,当前任务为蓝色,未来任务为绿色。灰色任务在遥远的未来,而划掉的任务(如果您选择显示它们)是已完成的任务。
事件和任务都可以是重复的,这意味着我们可以安排每周三下午 4 点的会议在接下来的十周内举行,而不是在日历中输入十个单独的事件。我们可以根据需要输入此类重复事件的例外情况,并且我们可以将它们设置为每隔几天、几个月或几年重复一次,“每隔几个”是用户可定义的。
Sunbird 构造这些事件和任务的方式强烈地反映了存储它们的 vCalendar 文件。虽然您可能期望现代互联网标准使用 XML,但 iCalendar 的文件格式由冒号 (:) 分隔的名称-值对组成。每个事件或任务都有自己的开始或结束行,并且整个日历文件类似地嵌套在整体开始和结束行之间。通常,iCalendar 文件中的每个名称-值对都位于单行上。但是,用任何空格缩进一行意味着它延续了上一行的数据,如下所示
name:value name2: value2 name3 :value3
上面的示例定义了三个名称-值对,每个名称-值对都略微不同地使用了空格。Sunbird 通常使用第三个选项,这样每个名称都位于单独的一行上,其关联的值缩进在后续行上。Sunbird 与其他 Mozilla 产品一样,将其所有数据文件都放在一个配置文件目录中,该目录的名称在您首次启动程序时随机创建。iCalendar 文件本身放置在配置文件目录中的 Calendar 子目录中。
iCalendar 的美妙之处在于,您无需将所有日历数据都放在一个文件中,甚至无需放在一台计算机上。符合 iCalendar 标准的程序显示来自它被指示读取的所有数据文件的所有日历数据的并集。因此,您可以在自己的计算机上拥有多个不同的日历文件,每个文件都反映您生活的不同方面,例如,个人与专业。您还可以从其他来源检索日历数据文件,包括通过 HTTP,这意味着组日历可以存储在公共服务器上,但在您自己的计算机上显示。
当您首次启动 Sunbird 或首次使用它创建日历时,程序会创建一个 CalendarDataFile.ics 文件。如果您有多个日历,则最终会在系统上获得许多此类文件。每个文件都命名为 CalendarDataFileN.ics,其中 N 代表您创建的日历的编号。
文件本身的结构非常简单。例如,这是一个包含单个事件的 iCalendar 文件,即本月的 Linux Journal 截止日期
BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :05e55cc2-1dd2-11b2-8818-f578cbb4b77d SUMMARY :LJ deadline STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART :20050211T140000 DTEND :20050211T150000 DTSTAMP :20050209T132231Z END:VEVENT END:VCALENDAR
如您所见,该文件以 VCALENDAR 声明开始和结束。每个事件都用 BEGIN:VEVENT 和 END:VEVENT 包围。然后,每个事件都有一个唯一的 ID;一个摘要,通常显示在日历中;一个状态;一个类别,指示您是否希望与他人共享此日历信息;然后是开始和结束时间。它还有一个时间戳,显示事件上次修改的时间。
iCalendar 文件中的时间戳遵循一种稍微奇怪的 YYYYMMDD 格式,表示日期,然后是一个 T,后跟 24 小时制时间,后跟一个可选时区和一个 Z。因为我目前住在芝加哥,所以时间戳表示的不是我输入条目的时间,而是比我提前六小时的时区的时间,比 GMT 晚一小时 (1Z)。
如果我有一个每月截止日期,并且我想将其包含在此日历事件中会发生什么?在 Sunbird 中,我可以通过双击事件进入事件编辑器的重复选项卡。在那里,我指示我希望此事件每月重复一次,这会更改界面,以便现在询问我它是否应该在每个月的 11 日——即在同一日期——还是在每个月的第二个星期五,相对于月份。如果我选择第一个,我的 iCalendar 文件看起来像这样
BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :05e55cc2-1dd2-11b2-8818-f578cbb4b77d SUMMARY :LJ deadline STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-RECUR-DEFAULT-UNITS :months RRULE :FREQ=MONTHLY;INTERVAL=1 DTSTART :20050211T140000 DTEND :20050211T150000 DTSTAMP :20050211T132231Z LAST-MODIFIED :20050211T153505Z END:VEVENT END:VCALENDAR
请注意,如何添加了 RRULE 属性,其值为 FREQ=MONTHLY 和 INTERVAL=1。您可以想象,如果我要将此截止日期更改为每两周一次,则它将是 FREQ=WEEKLY 和 INTERVAL=2。这是正确的,但它也添加了一个 BYDAY=FR 字段,指示事件发生在星期五。
如果我选择使此事件在每个月的第二个星期五发生,则 iCalendar 文件看起来像这样
BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :05e55cc2-1dd2-11b2-8818-f578cbb4b77d SUMMARY :LJ deadline STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-RECUR-DEFAULT-UNITS :months RRULE :FREQ=MONTHLY;INTERVAL=1;BYDAY=2FR DTSTART :20050211T140000 DTEND :20050211T150000 DTSTAMP :20050211T132231Z LAST-MODIFIED :20050211T153824Z END:VEVENT END:VCALENDAR
请注意,我们的 RRULE 属性现在是 FREQ=MONTHLY,因为这每月发生一次,INTERVAL=1。另请注意,已添加了 BYDAY=2FR,这意味着该事件发生在每个月的第二个星期五。
最后,让我们利用 Sunbird 具有远程日历的能力,将此文件移出我们的目录并移到另一个系统上。我将 CalendarDataFile7.ics 文件(之所以这样命名是因为它是我创建的第七个日历)移动到 /tmp。然后我将其复制到我的网站,以便可以通过 URL http://reuven.lerner.co.il/CalendarDataFile7.ics 访问。我通过尝试使用 wget 下载它来仔细检查该文件是否可以从此 URL 访问。当我看到它工作正常时,我知道我可以将此信息放入 Sunbird。
现在我进入 Sunbird 并删除 ATF 日历;Sunbird 不会让您删除现有本地日历的文件名。然后我从“文件”菜单中选择“订阅远程日历”,并输入我放置 .ics 文件的 URL。下载日历后,我每月都会在日历上看到 LJ 截止日期事件,就像它在我的本地机器上一样。事实上,如果您查看 Calendar 目录,您可以看到该文件 确实 在您的本地机器上。它已被下载并安装到该目录中,并且可以在您请求时随时刷新。只需右键单击日历名称并选择“重新加载远程日历”)。
我们对混合桌面-Web 应用程序的调查始于使用 Mozilla 独立 Sunbird 应用程序检查 iCalendar/vCalendar 文件格式。我们能够创建不同类型的事件,然后将生成的 iCalendar 文件从我们的本地机器移动到远程服务器。
但是,我们的日历是静态的,这意味着每次更改时都必须手动修改它或上传日历文件。在我的下一篇专栏文章中,我们将学习如何使用 Web/数据库应用程序动态创建 iCalendar 文件。然后,我们将研究在另一台计算机上创建的日历可以写入服务器并与其他人共享的不同方式。
本文资源: /article/8128。
Reuven M. Lerner,一位长期的 Web/数据库顾问和开发人员,现在是西北大学学习科学专业的 graduate student。他的 Weblog 在 altneuland.lerner.co.il,您可以通过 reuven@lerner.co.il 与他联系。