日历标准格式

时间:2022-07-21
本文章向大家介绍日历标准格式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

概述

通用的日历格式是 iCalendar,通常扩展名是.ics

iCalendar允许用户通过电子邮件的方式发送“会议请求”或“任务”。收信人使用支持iCalendar邮件客户端,便可以很方便地回应发件人,接受请求或另外提议一个新的会议时间。

维基百科中关于 iCalendar 的描述是: https://zh.wikipedia.org/wiki/ICalendar

标准

具体参考的标准是 RFC 5545

一般 ics 文件的格式

BEGIN:VCALENDAR                                  # 日历开始
PRODID:-//test.us//iCalendar Event//EN           # 软件信息
VERSION:2.0                                      # 遵循的 iCalendar 版本号
CALSCALE:GREGORIAN                               # 历法:公历
METHOD:PUBLISH                                   # 方法:公开 也可以是 REQUEST 等用于日历间的信息沟通方法
CLASS:PUBLIC                                     # Classification 此属性定义日历组件的访问分类: "PUBLIC" / "PRIVATE" / "CONFIDENTIAL" / iana-token / x-name
BEGIN:VTIMEZONE                                  # Time Zone Component
TZID:Asia/Shanghai                               # Time Zone Identifier 时区标识符
TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Shanghai            # Time Zone URL: 访问 http://tzurl.azureedge.net/zoneinfo-outlook/Asia
X-LIC-LOCATION:Asia/Shanghai
BEGIN:STANDARD
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
TZNAME:CST
DTSTART:19700101T000000
END:STANDARD
END:VTIMEZONE                                     # 时区组件结束
BEGIN:VEVENT                                      # 事件开始
DTSTAMP:20190723T071307Z                          # 有 Method 属性时表示 实例创建时间,没有时表示最后修订的日期时间
DTSTART;TZID=Asia/Shanghai:20191024T150000        # 开始的日期时间
DTEND;TZID=Asia/Shanghai:20191024T160000          # 结束的日期时间
SUMMARY:我的会议                                   # 简介 一般是标题
# UID (唯一标识符)
UID:20190723T071307Z-105904298@fe80:0:0:0:e4:cbff:fe80:b24c%ens5                  
# Time Zone Identifier 时区标识符
TZID:Asia/Shanghai                                                                
# 描述
DESCRIPTION:issac 的描述  
# 地址                                              
LOCATION:https://cloud.tencent.com/developer/user/6258660      
# Alarm Component 报警组件                                
BEGIN:VALARM    
# 触发 alarm (开始之前10分钟提醒)                                                                  
TRIGGER:-PT10M  
# AUDIODISPLAYEMAIL                                                                  
ACTION:DISPLAY     
# In a DISPLAY alarm, the intended alarm effect is for 
# the text value of the "DESCRIPTION" property to be displayed to the user. 
DESCRIPTION:Reminder  
# alarm 结束                                 
END:VALARM   
# 事件结束                                                                     
END:VEVENT    
# 日历结束                                                                    
END:VCALENDAR

设置日历周期性重复

# 重复规则 rrule (Recurrence Rule):
RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20190917T133000;INTERVAL=1;BYDAY=TU

重复规则 rrule (Recurrence Rule)

重复规则包含多个属性, 每个属性以 NAME = VALUE 对的形式存在, 属性与属性之间用分号区分, 属性之间没有特定的顺序要求,在同一个重复规则中每个属性最多只能出现一次。

1、FREQ

FREQ 属性表示重复规则的类型,可选的 VALUE 有:

  • SECONDLY, 表示以秒为间隔单位进行重复。
  • MINUTELY, 表示以分钟为间隔单位进行重复。
  • HOURLY, 表示以小时为间隔单位进行重复。
  • DAILY, 表示以天为间隔单位进行重复。
  • WEEKLY, 表示以周为间隔单位进行重复。
  • MONTHLY, 表示以月为间隔单位进行重复。
  • YEARLY, 表示以年为间隔单位进行重复。

2、WKST

WKST 取值范围 MO(周一), TU(周二), WE(周三), TU(周四), FR(周五), SA(周六), SU(周日)。 默认值为 MO。

当一个 WEEKLY 类型的重复规则, INTERVAL 大于 1, 且带有 BYDAY 属性时, 则必须带有 WKST 属性。 当一个 YEARLY 类型的重复规则带有 BYWEEKNO 属性时, 也必须带有 WKST 属性。

3、UNTIL

UNTIL 属性定义了一个日期-时间值,用以限制重复规则。

这个日期-时间值表示这个重复规则的最后一次事件的发生时间。

如果重复规则中未包含 UNTIL 和 COUNT 属性, 则表示该重复规则无限重复。

4、INTERVAL

INTERVAL 属性表示重复规则的间隔, 必须为正整数。 默认值为1。

对应上述不同的 FREQ 值分别表示每一秒,每一分钟, 每一小时, 每一天, 每一周, 每一月, 每一年。s

5、BYDAY

BYDAY 取值范围: MO(周一), TU(周二), WE(周三), TU(周四), FR(周五), SA(周六), SU(周日)。可以有多个值,用逗号分隔。

每个值可以在前面加上一个正整数(+n)或者负整数(-n),用以在 MONTHLY 或者 YEARLY 的重复类型中表示第 n 个周几。 例如,在一个 MONTHLY 类型的重复规则中, +1MO(或者1MO)表示这个月的第1个周一,如果是 -1MO 则表示这个月的最后1个周一。

如果前面没有数字,则表示在这个重复类型中的所有的周几, 比如在一个 MONTHLY 的重复类型中, MO 表示这个月里所有的周一。

与 Google 日历同步

调用 Google Calendar API 的 demo

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import BaseHTTPServer
import httplib2
import urlparse

from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    """Child class of BaseHTTPRequestHandler that only handles GET request."""
    # https://developers.google.com/calendar/quickstart/js
    clientID = '295995113385-nu8em9928itnt7fa92dc5ab1tv710ojs.apps.googleusercontent.com'
    apiKey = 'YFzGsExw6fURfmysfxr1lvpF'
    authUrl = 'https://www.googleapis.com/auth/calendar'
    flow = OAuth2WebServerFlow(clientID, apiKey, authUrl, redirect_uri='http://localhost:8080/')

    def do_GET(self):
        """Handler for GET request."""
        print 'nnNEW REQUEST, Path: %s' % (self.path)

        if self.path.startswith('/?fake_user='):
            self.handle_initial_url()
        # When you redirect to the authorization server below, it redirects back
        # to to http://localhost:8080/?code=<some_code> after the user grants access
        # permission for your application.
        elif self.path.startswith('/?code='):
            self.handle_redirected_url()
        else:
            self.respond_ignore() # Either an error from auth server or bad user entered URL.

    def handle_initial_url(self):
        """Handles the initial path."""
        parsed = urlparse.urlparse(self.path)
        fake_user = urlparse.parse_qs(parsed.query)['fake_user'][0]
        self.respond_redirect_to_auth_server(fake_user)

    def respond_redirect_to_auth_server(self, fake_user):
        """Respond to the current request by redirecting to the auth server."""
        uri = RequestHandler.flow.step1_get_authorize_url()
        print 'Redirecting %s to %s' % (fake_user, uri)

        self.send_response(301)
        self.send_header('Cache-Control', 'no-cache')
        self.send_header('Location', uri)
        self.end_headers()

    def handle_redirected_url(self):
        """Handles the redirection back from the authorization server."""
        # The server should have responded with a "code" URL query parameter. This is needed to acquire credentials.
        parsed = urlparse.urlparse(self.path)
        code = urlparse.parse_qs(parsed.query)['code'][0]
        credentials = RequestHandler.flow.step2_exchange(code)
        http = httplib2.Http()
        http = credentials.authorize(http)
        service = build('calendar', 'v3', http=http)

        event = {
            # 'summary': 'Google I/O 2015',
            'summary': 'tttttt',
            'location': '800 Howard St., San Francisco, CA 94103',
            'description': 'A chance to hear more about Google's developer products.',
            'start': {
                'dateTime': '2019-08-18T09:00:00-07:00',
                'timeZone': 'America/Los_Angeles',
            },
            'end': {
                'dateTime': '2019-08-18T17:00:00-07:00',
                'timeZone': 'America/Los_Angeles',
            },
            'recurrence': [
                # 'RRULE:FREQ=DAILY;COUNT=2'
                # 'RRULE:FREQ=WEEKLY' # 每周重复
                # 'RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20200121T133000;INTERVAL=4;BYDAY=TU' # 报错了
            ],
            'attendees': [
                {'email': 'lpage@example.com'},
                {'email': 'sbrin@example.com'},
            ],
            'reminders': {
                'useDefault': False,
                'overrides': [
                    # {'method': 'email', 'minutes': 24 * 60},
                    {'method': 'popup', 'minutes': 15},
                ],
            },
        }

        res = service.events().insert(calendarId='primary', body=event).execute()
        parsed = urlparse.urlparse(res.get('htmlLink'))
        eidCode = urlparse.parse_qs(parsed.query)['eid'][0]
        eventeditUrl = 'https://calendar.google.com/calendar/r/eventedit/' + eidCode
        print '>>> eventeditUrl: %s' % (eventeditUrl)
        self.send_response(301)
        self.send_header('Cache-Control', 'no-cache')
        self.send_header('Location', eventeditUrl)
        self.end_headers()

    def respond_ignore(self):
        """Responds to the current request that has an unknown path."""
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.send_header('Cache-Control', 'no-cache')
        self.end_headers()
        self.wfile.write(
            'This path is invalid or user denied access:n%snn' % self.path)
        self.wfile.write(
            'User entered URL should look like: http://localhost:8080/?fake_user=johndoe')

def main():
    try:
        server = BaseHTTPServer.HTTPServer(('', 8080), RequestHandler)
        print 'Starting server. Use Control+C to stop.'
        server.serve_forever()
    except KeyboardInterrupt:
        print 'Shutting down server.'
        server.socket.close()


if __name__ == '__main__':
    main()

Google Calendar API 参考资料

与 outlook 日历同步

the Outlook REST API

Use the Outlook REST API

Outlook calendar API

Outlook calendar API

Outlook 加载项

add-ins 加载项