using System;
using System.Text;
using System.Text.RegularExpressions;
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace com.google.zxing.client.result
{
///
/// @author Sean Owen
///
public sealed class CalendarParsedResult : ParsedResult
{
private static readonly string RFC2445_DURATION = "P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?";
private static readonly long[] RFC2445_DURATION_FIELD_UNITS = {7 * 24 * 60 * 60 * 1000L, 24 * 60 * 60 * 1000L, 60 * 60 * 1000L, 60 * 1000L, 1000L};
private static readonly string DATE_TIME = "[0-9]{8}(T[0-9]{6}Z?)?";
private static readonly string DATE_FORMAT = "yyyyMMdd";
static CalendarParsedResult()
{
// For dates without a time, for purposes of interacting with Android, the resulting timestamp
// needs to be midnight of that day in GMT. See:
// http://code.google.com/p/android/issues/detail?id=8330
string DATE_FORMAT_TimeZone = "GMT";
}
private static readonly string DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmss";
private readonly string summary;
private readonly DateTime start;
private readonly bool startAllDay;
private readonly DateTime? end;
private readonly bool endAllDay;
private readonly string location;
private readonly string organizer;
private readonly string[] attendees;
private readonly string description;
private readonly double latitude;
private readonly double longitude;
public CalendarParsedResult(string summary, string startString, string endString, string durationString, string location, string organizer, string[] attendees, string description, double latitude, double longitude) : base(ParsedResultType.CALENDAR)
{
this.summary = summary;
try
{
this.start = parseDate(startString);
}
catch (FormatException pe)
{
throw new System.ArgumentException(pe.ToString());
}
if (endString == null)
{
long durationMS = parseDurationMS(durationString);
end = durationMS < 0L ? null :(DateTime?) start.AddMilliseconds( durationMS);
}
else
{
try
{
this.end = parseDate(endString);
}
catch (FormatException pe)
{
throw new System.ArgumentException(pe.ToString());
}
}
this.startAllDay = startString.Length == 8;
this.endAllDay = endString != null && endString.Length == 8;
this.location = location;
this.organizer = organizer;
this.attendees = attendees;
this.description = description;
this.latitude = latitude;
this.longitude = longitude;
}
public string Summary
{
get
{
return summary;
}
}
/// start time
public DateTime Start
{
get
{
return start;
}
}
/// true if start time was specified as a whole day
public bool StartAllDay
{
get
{
return startAllDay;
}
}
///
/// May return null if the event has no duration.
///
public DateTime? End
{
get
{
return end;
}
}
/// true if end time was specified as a whole day
public bool EndAllDay
{
get
{
return endAllDay;
}
}
public string Location
{
get
{
return location;
}
}
public string Organizer
{
get
{
return organizer;
}
}
public string[] Attendees
{
get
{
return attendees;
}
}
public string Description
{
get
{
return description;
}
}
public double Latitude
{
get
{
return latitude;
}
}
public double Longitude
{
get
{
return longitude;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(100);
maybeAppend(summary, result);
maybeAppend(format(startAllDay, start), result);
maybeAppend(format(endAllDay, end), result);
maybeAppend(location, result);
maybeAppend(organizer, result);
maybeAppend(attendees, result);
maybeAppend(description, result);
return result.ToString();
}
}
///
/// Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021)
/// or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC).
///
/// The string to parse
/// if not able to parse as a date
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static java.util.Date parseDate(String when) throws java.text.ParseException
private static DateTime parseDate(string when)
{
if (!(new Regex (DATE_TIME).IsMatch(when)))
{
throw FormatException.FormatInstance;
}
if (when.Length == 8)
{
// Show only year/month/day
return DateTime.Parse(when);
}
else
{
// The when string can be local time, or UTC if it ends with a Z
DateTime date;
if (when.Length == 16 && when[15] == 'Z')
{
date = DateTime.Parse(when.Substring(0, 15));
//DateTime calendar = new GregorianCalendar();
// System.Globalization.GregorianCalendar calendar = new System.Globalization.GregorianCalendar()
//long milliseconds = date;
//// Account for time zone difference
//milliseconds += calendar.get(DateTime.ZONE_OFFSET);
//// Might need to correct for daylight savings time, but use target time since
//// now might be in DST but not then, or vice versa
//calendar = new DateTime(milliseconds);
//milliseconds += calendar.get(DateTime.DST_OFFSET);
TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(date);
date = date + offset;
}
else
{
date = DateTime.Parse(when);
}
return date;
}
}
private static string format(bool allDay, DateTime? date)
{
if (date == null)
{
return null;
}
//DateFormat format = allDay ? DateFormat.getDateInstance(DateFormat.MEDIUM) : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
//return format.format(date);
if (allDay)
{
return String.Format("dd-MMM-yyyy",date);
}
else
{
return String.Format("dd-MMM-yyyy hh:mm:ss tt",date);
}
}
private static long parseDurationMS(string durationString)
{
if (durationString == null)
{
return -1L;
}
Regex m = new Regex(RFC2445_DURATION);
Match match = m.Match(durationString);
if (!match.Success)
{
return -1L;
}
long durationMS = 0L;
for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.Length; i++)
{
string fieldValue = match.Groups[i + 1].Value;
if (fieldValue != null)
{
durationMS += RFC2445_DURATION_FIELD_UNITS[i] * Convert.ToInt32(fieldValue);
}
}
return durationMS;
}
}
}