Skip to content
Open
102 changes: 89 additions & 13 deletions GTFSimple.Core/Csv/Converters.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,113 @@
using System;
using System.Globalization;
using CsvHelper.TypeConversion;

namespace GTFSimple.Core.Csv
{
internal class OneZeroConverter : DefaultTypeConverter
internal class DateConverter : GenericTypeConverter<DateTime>
{
public override bool CanConvertFrom(Type type)
protected override string Format(CultureInfo culture, DateTime value)
{
return value.ToString("yyyyMMdd");
}

protected override DateTime Parse(CultureInfo culture, string text)
{
return DateTime.ParseExact(text, "yyyyMMdd", culture, DateTimeStyles.None);
}
}

internal class BooleanOneZeroConverter : GenericTypeConverter<bool?>
{
protected override string Format(CultureInfo culture, bool? value)
{
return value == null ? "" : value.Value ? "1" : "0";
}

protected override bool? Parse(CultureInfo culture, string text)
{
switch (text)
{
case "1":
return true;
case "0":
return false;
case null:
return null;
default:
throw new NotSupportedException("The conversion cannot be performed.");
}
}
}

internal class TimeSpanSecondsConverter : GenericTypeConverter<TimeSpan?>
{
protected override string Format(CultureInfo culture, TimeSpan? value)
{
return value == null ? "" : value.Value.TotalSeconds.ToString(culture);
}

protected override TimeSpan? Parse(CultureInfo culture, string text)
{
return new TimeSpan(0, 0, int.Parse(text, culture));
}
}

internal class TimeSpanHourMinuteSecondConverter : GenericTypeConverter<TimeSpan?>
{
protected override string Format(CultureInfo culture, TimeSpan? value)
{
return type == typeof(bool);
return value == null ? "" : value.Value.ToString("c");
}

public override string ConvertToString(object value)
protected override TimeSpan? Parse(CultureInfo culture, string text)
{
if (value is bool)
return (bool)value ? "1" : "0";
return TimeSpan.Parse(text, culture);
}
}

return base.ConvertToString(value);
internal class UriConverter : GenericTypeConverter<Uri>
{
protected override string Format(CultureInfo culture, Uri value)
{
return value == null ? "" : value.ToString();
}

protected override Uri Parse(CultureInfo culture, string text)
{
return new Uri(text);
}
}

internal class TimeSpanConverter : DefaultTypeConverter
internal abstract class GenericTypeConverter<T> : DefaultTypeConverter
{
protected abstract string Format(CultureInfo culture, T value);

protected abstract T Parse(CultureInfo culture, string text);

public override bool CanConvertFrom(Type type)
{
return type == typeof(TimeSpan);
return type == typeof(string);
}

public override bool CanConvertTo(Type type)
{
return type == typeof(string);
}

public override string ConvertToString(object value)
public override object ConvertFromString(CultureInfo culture, string text)
{
if (value is TimeSpan)
return ((TimeSpan)value).TotalSeconds.ToString();
return string.IsNullOrEmpty(text) ? default(T) : Parse(culture, text);
}

return base.ConvertToString(value);
public override object ConvertFromString(string text)
{
return ConvertFromString(CultureInfo.InvariantCulture, text);
}

public override string ConvertToString(CultureInfo culture, object value)
{
return Format(culture, (T)value);
}
}
}
7 changes: 5 additions & 2 deletions GTFSimple.Core/Feed/Agency.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("agency")]
public class Agency
{
[FieldName("agency_id")]
Expand All @@ -11,7 +14,7 @@ public class Agency
[FieldName("agency_name")]
public string Name { get; set; }

[FieldName("agency_url")]
[FieldName("agency_url"), TypeConverter(typeof(UriConverter))]
public Uri Url { get; set; }

[FieldName("agency_timezone")]
Expand All @@ -23,7 +26,7 @@ public class Agency
[FieldName("agency_phone")]
public string Phone { get; set; }

[FieldName("agency_fare_url")]
[FieldName("agency_fare_url"), TypeConverter(typeof(UriConverter))]
public Uri FareUrl { get; set; }
}
}
48 changes: 39 additions & 9 deletions GTFSimple.Core/Feed/Calendar.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,69 @@
using System;
using System.Collections.Generic;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("calendar")]
public class Calendar
{
[FieldName("service_id")]
public string ServiceId { get; set; }

[FieldName("monday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("monday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Monday { get; set; }

[FieldName("tuesday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("tuesday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Tuesday { get; set; }

[FieldName("wednesday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("wednesday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Wednesday { get; set; }

[FieldName("thursday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("thursday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Thursday { get; set; }

[FieldName("friday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("friday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Friday { get; set; }

[FieldName("saturday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("saturday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Saturday { get; set; }

[FieldName("sunday"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("sunday"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool Sunday { get; set; }

[FieldName("start_date", Format = "{0:yyyyMMdd}")]
[FieldName("start_date"), TypeConverter(typeof(DateConverter))]
public DateTime StartDate { get; set; }

[FieldName("end_date", Format = "{0:yyyyMMdd}")]
[FieldName("end_date"), TypeConverter(typeof(DateConverter))]
public DateTime EndDate { get; set; }

public override string ToString()
{
return string.Format("{0} for {1:yyyy-MM-dd} to {2:yyyy-MM-dd}: {3}",
ServiceId, StartDate, EndDate, string.Join("", Days));
}

private IEnumerable<string> Days
{
get
{
if (Monday)
yield return "M";
if (Tuesday)
yield return "T";
if (Wednesday)
yield return "W";
if (Thursday)
yield return "H";
if (Friday)
yield return "F";
if (Saturday)
yield return "S";
if (Sunday)
yield return "U";
}
}
}
}
11 changes: 10 additions & 1 deletion GTFSimple.Core/Feed/CalendarDate.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
using System;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("calendar_dates")]
public class CalendarDate
{
[FieldName("service_id")]
public string ServiceId { get; set; }

[FieldName("date", Format = "{0:yyyyMMdd}")]
[FieldName("date"), TypeConverter(typeof(DateConverter))]
public DateTime Date { get; set; }

[FieldName("exception_type", Format = "{0:D}")]
public ExceptionType ExceptionType { get; set; }

public override string ToString()
{
return string.Format("{0} on {1:yyyy-MM-dd}: {2}",
ServiceId, Date, ExceptionType);
}
}

public enum ExceptionType
Expand Down
10 changes: 9 additions & 1 deletion GTFSimple.Core/Feed/FareAttributes.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("fare_attributes")]
public class FareAttributes
{
[FieldName("fare_id")]
Expand All @@ -21,8 +23,14 @@ public class FareAttributes
[FieldName("transfers", Format = "{0:D}")]
public FareTransferType? Transfers { get; set; }

[FieldName("transfer_duration"), TypeConverter(typeof(TimeSpanConverter))]
[FieldName("transfer_duration"), TypeConverter(typeof(TimeSpanSecondsConverter))]
public TimeSpan? TransferDuration { get; set; }

public override string ToString()
{
return string.Format("{0}: {1:0.00} {2} ({3})",
FareId, Price, CurrencyType, PaymentMethod);
}
}

public enum PaymentMethod
Expand Down
2 changes: 2 additions & 0 deletions GTFSimple.Core/Feed/FareRules.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("fare_rules")]
public class FareRules
{
[FieldName("fare_id")]
Expand Down
7 changes: 5 additions & 2 deletions GTFSimple.Core/Feed/FeedInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
Expand All @@ -9,6 +11,7 @@ namespace GTFSimple.Core.Feed
/// However, the publisher of the feed is sometimes a different entity than any of the agencies (in the case of regional aggregators).
/// In addition, there are some fields that are really feed-wide settings, rather than agency-wide.
/// </summary>
[FeedFile("feed_info")]
public class FeedInfo
{
/// <summary>
Expand Down Expand Up @@ -59,7 +62,7 @@ public class FeedInfo
/// the feed is making an explicit assertion that there is no service for dates within the feed_start_date or feed_end_date range but not included in the active calendar dates.
/// </summary>
/// <value>The feed start date.</value>
[FieldName("feed_start_date", Format = "{0:yyyyMMdd}")]
[FieldName("feed_start_date"), TypeConverter(typeof(DateConverter))]
public DateTime? FeedStartDate { get; set; }

/// <summary>
Expand All @@ -74,7 +77,7 @@ public class FeedInfo
/// the feed is making an explicit assertion that there is no service for dates within the feed_start_date or feed_end_date range but not included in the active calendar dates.
/// </summary>
/// <value>The feed end date.</value>
[FieldName("feed_end_date", Format = "{0:yyyyMMdd}")]
[FieldName("feed_end_date"), TypeConverter(typeof(DateConverter))]
public DateTime? FeedEndDate { get; set; }

/// <summary>
Expand Down
10 changes: 6 additions & 4 deletions GTFSimple.Core/Feed/Frequency.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
using System;
using CsvHelper.TypeConversion;
using GTFSimple.Core.Csv;
using GTFSimple.Core.Files;

namespace GTFSimple.Core.Feed
{
[FeedFile("frequencies")]
public class Frequency
{
[FieldName("trip_id")]
public string TripId { get; set; }

[FieldName("start_time")]
[FieldName("start_time"), TypeConverter(typeof(TimeSpanHourMinuteSecondConverter))]
public TimeSpan StartTime { get; set; }

[FieldName("end_time")]
[FieldName("end_time"), TypeConverter(typeof(TimeSpanHourMinuteSecondConverter))]
public TimeSpan EndTime { get; set; }

[FieldName("headway_secs"), TypeConverter(typeof(TimeSpanConverter))]
[FieldName("headway_secs"), TypeConverter(typeof(TimeSpanSecondsConverter))]
public TimeSpan Headway { get; set; }

[FieldName("exact_times"), TypeConverter(typeof(OneZeroConverter))]
[FieldName("exact_times"), TypeConverter(typeof(BooleanOneZeroConverter))]
public bool? ExactTimes { get; set; }
}
}
Loading