2017-02-17 75 views
1

我試圖製作一個腳本,我在互聯網上找到與我的ics文件一起工作,所以我可以將它添加到我的項目中。Javascript iCal解析器腳本忽略Tmezone

如果我從ics文件中刪除時區部分,該腳本可以正常工作。 但是由於該文件將從互聯網上動態獲取,因此我無法在旅途中對其進行編輯。 所以不知怎的,我不得不修改我的代碼跳過或使用該部分。

的代碼是(Source):

/** 
* Javascript ical Parser 
* Proof of concept method of reading icalendar (.ics) files with javascript. 
* 
* @author: Carl Saggs 
* @source: https://github.com/thybag/ 
* @version: 0.2 
*/ 
function ical_parser(feed_url, callback){ 
    //store of unproccesed data. 
    this.raw_data = null; 
    //Store of proccessed data. 
    this.events = []; 

    /** 
    * loadFile 
    * Using AJAX to load the requested .ics file, passing it to the callback when completed. 
    * @param url URL of .ics file 
    * @param callback Function to call on completion. 
    */ 
    this.loadFile = function(url, callback){ 
     //Create request object 
     try {xmlhttp = window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { } 
     //Grab file 
     xmlhttp.onreadystatechange = function(){ 
      if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200)) { 
       //On success, run callback. 
       callback(xmlhttp.responseText); 
      } 
     } 
     xmlhttp.open("GET", url, true); 
     xmlhttp.send(null); 
    } 

    /** 
    * makeDate 
    * Convert the dateformat used by ICalendar in to one more suitable for javascript. 
    * @param String ical_date 
    * @return dt object, includes javascript Date + day name, hour/minutes/day/month/year etc. 
    */ 
    this.makeDate = function(ical_date){ 
     //break date apart 
     var dt = { 
      year: ical_date.substr(0,4), 
      month: ical_date.substr(4,2), 
      day: ical_date.substr(6,2), 
      hour: ical_date.substr(9,2), 
      minute: ical_date.substr(11,2) 
     } 
     //Create JS date (months start at 0 in JS - don't ask) 
     dt.date = new Date(dt.year, (dt.month-1), dt.day, dt.hour, dt.minute); 
     //Get the full name of the given day 
     dt.dayname =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][dt.date.getDay()]; 
     return dt; 
    } 

    /** 
    * parseICAL 
    * Convert the ICAL format in to a number of javascript objects (Each representing a date) 
    * 
    * @param data Raw ICAL data 
    */ 
    this.parseICAL = function(data){ 
     //Ensure cal is empty 
     this.events = []; 

     //Clean string and split the file so we can handle it (line by line) 
     cal_array = data.replace(new RegExp("\\r", "g"), "").split("\n");  
     //Keep track of when we are activly parsing an event 
     var in_event = false; 
     //Use as a holder for the current event being proccessed. 
     var cur_event = null; 
     for(var i=0;i<cal_array.length;i++){ 
      ln = cal_array[i]; 
      //If we encounted a new Event, create a blank event object + set in event options. 
      if(!in_event && ln == 'BEGIN:VEVENT'){ 
       in_event = true; 
       cur_event = {}; 
      } 
      //If we encounter end event, complete the object and add it to our events array then clear it for reuse. 
      if(in_event && ln == 'END:VEVENT'){ 
       in_event = false; 
       this.events.push(cur_event); 
       cur_event = null; 
      } 
      //If we are in an event 
      if(in_event){ 
       //Split the item based on the first ":" 
       idx = ln.indexOf(':'); 
       //Apply trimming to values to reduce risks of badly formatted ical files. 
       type = ln.substr(0,idx).replace(/^\s\s*/, '').replace(/\s\s*$/, '');//Trim 
       val = ln.substr(idx+1,ln.length-(idx+1)).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 

       //If the type is a start date, proccess it and store details 
       if(type.indexOf('DTSTART') != -1){ 
        dt = this.makeDate(val); 
        val = dt.date; 
        //These are helpful for display 
        cur_event.start_time = dt.hour+':'+dt.minute; 
        cur_event.start_date = dt.day+'/'+dt.month+'/'+dt.year; 
        cur_event.day = dt.dayname; 
       } 
       //If the type is an end date, do the same as above 
       if(type.indexOf('DTEND') != -1){ 
        dt = this.makeDate(val); 
        val = dt.date; 
        //These are helpful for display 
        cur_event.end_time = dt.hour+':'+dt.minute; 
        cur_event.end_date = dt.day+'/'+dt.month+'/'+dt.year; 
        cur_event.day = dt.dayname; 
       } 
       //Convert timestamp 
       if(type =='DTSTAMP') val = this.makeDate(val).date; 

       //Add the value to our event object. 
       cur_event[type] = val; 
       //console.log(cur_event); 
      } 
     } 
     //Run this to finish proccessing our Events. 
     this.complete(); 
    } 
    /** 
    * complete 
    * Sort all events in to a sensible order and run the original callback 
    */ 
    this.complete = function(){ 
     //Sort the data so its in date order. 
     this.events.sort(function(a,b){ 
      return a.DTSTART-b.DTSTART; 
     }); 
     //Run callback method, if was defined. (return self) 
     if(typeof callback == 'function') callback(this); 
    } 
    /** 
    * getEvents 
    * return all events found in the ical file. 
    * 
    * @return list of events objects 
    */ 
    this.getEvents = function(){ 
     return this.events; 
    } 

    /** 
    * getFutureEvents 
    * return all events sheduled to take place after the current date. 
    * 
    * @return list of events objects 
    */ 
    this.getFutureEvents = function(){ 
     var future_events = [], current_date = new Date(); 

     this.events.forEach(function(itm){ 
      //If the event starts after the current time, add it to the array to return. 
      if(itm.DTSTART > current_date) future_events.push(itm); 
      console.log(itm); 
     }); 
     return future_events; 
    } 

    /** 
    * load 
    * load a new ICAL file. 
    * 
    * @param ical file url 
    */ 
    this.load = function(ical_file){ 
     var tmp_this = this; 
     this.raw_data = null; 
     this.loadFile(ical_file, function(data){ 
      //if the file loads, store the data and invoke the parser 
      tmp_this.raw_data = data; 
      tmp_this.parseICAL(data); 
     }); 
    } 

    //Store this so we can use it in the callback from the load function. 
    var tmp_this = this; 
    //Store the feed url 
    this.feed_url = feed_url; 
    //Load the file 
    this.load(this.feed_url); 
} 

我認爲這個問題的getFutureEvents,其當前的日期與文件上的日期開始比較。

我的文件看起來像:

BEGIN:VEVENT 
    DTSTAMP:20170217T034951Z 
    DTSTART;TZID=Europe/London:20170330T090000 
    DTEND;TZID=Europe/London:20170330T100000 
    SUMMARY:Blah Blah Blah 
    LOCATION:Blah 0.20 
    DESCRIPTION:Week Number: 9\nBuilding: Blah\nRoom: 0.30\nUnit Ref: U 
    87454/n 
    Lecturer: Blah\,Blah 
    LAST-MODIFIED:20170217T034950Z 
    END:VEVENT 

樣品ics文件看起來像:

BEGIN:VEVENT 
UID:[email protected] 
DTSTAMP:20120120T130000Z 
ORGANIZER;CN=Test:MAILTO:[email protected] 
DTSTART:20120507T130000Z 
DTEND:20120507T140000Z 
SUMMARY:Intro to Witchcraft and wizardry 
DESCRIPTION:A Description of this Event here 
END:VEVENT 
+0

你能告訴我你如何期待你的文件被解釋?我認爲這就是要做的一切,但我必須知道你想要的最終格式。特別是你的'描述'字段引起了我的懷疑。那是一行還是三行? –

+0

作爲第一步我真的需要做的是以某種方式從文件中刪除任何可能的時區。例如,某些文件具有DTSTART; TZID =歐洲/倫敦:20170330T090000。但爲了讓iCal Parser閱讀它,不應包含Timezone。所以這條線應該是DTSTART:20170330T090000。 ; TZID =歐洲/倫敦應該被刪除。我認爲在這裏我們需要一個正則表達式來刪除所有內容;和:(包括;) – Bobys

+0

我真的不需要描述。只需DTSART,DTEND,摘要和位置。其餘的將被iCal解析器跳過。 – Bobys

回答

1

我編輯的parseICAL方法,它似乎是足夠的,現在您的需求(但仍不完美)。有我的變化:

this.parseICAL = function(data){ 
    /* ... */ 
    for(var i=0;i<cal_array.length;i++){ 
    ln = cal_array[i]; 
    ln = ln.trim(); // <-- here I'm trimming every line, because I noticed 
        // that spaces was causing some problems 

    /* ... */ 
    if(in_event){ 
     idx = ln.indexOf(':'); 
     type = ln.substr(0,idx).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 
     val = ln.substr(idx+1,ln.length-(idx+1)).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 
     type = type.split(';')[0]; // <-- and here I am removing everything 
           // after semicolon in types 

     /* ... */ 
    } 
    } 
    this.complete(); 
} 

我希望它現在能夠工作,它爲我工作。

+0

謝謝你的回答,我明天再看看。這似乎很好,但。我會很快回復你Karol。 – Bobys

+1

謝謝,卡羅爾。它按預期工作!我感謝你的時間和精力! – Bobys