When it comes to formatting dates and time strings, people seem to forget (I don't blame them) and mixes up stuff like M
vs m
; which one is months and which one is minutes? And how many characters was it to get abbreviation instead of month number? I took a few minutes, violated some principles and put together a simple fluent API with semantic meanings in the formating process. Now, it will not cover everything, but you will get the idea.
Lets have a look at how you can put it to use:
static void Main(string[] args)
{
var f = F.Date
.Year().And()
.Month().And()
.Day()
.Time.Hour().And()
.Minute();
var s = DateTime.Now.ToString(f, CultureInfo.InvariantCulture);
Console.WriteLine(s);
}
yields
=> 2014-03-18 19:07
Now, I have set some defaults here, so the TimeFormat
class, returned by the final Minute()
call, will return: yyyy-MM-dd HH:mm
.
Lets say I would like to have something like: 18-Mar, 2014 19:07
, you would then consume it like this:
var f = F.Date
.Day().And()
.Month(m => m.Abbreviation).And(',')
.Year()
.Time.Hour().And()
.Minute();
which produces the format: dd-MMM, yyyy HH:mm
.
Again, just a simple example put together in a hurry. The point is that you can put semantics into plumbing code as well.
Cheers,
//Daniel
public static class F
{
public class Year
{
public static class As
{
public const int Century = 4;
public const int Decade = 2;
public const int Single = 1;
}
private static readonly Lazy<Year> InstanceFn =
new Lazy<Year>(() => new Year());
public static Year Instance { get { return InstanceFn.Value; } }
private Year() { }
public int Century { get { return As.Century; } }
public int Decade { get { return As.Decade; } }
public int Single { get { return As.Single; } }
}
public class Month
{
public static class As
{
public const int Full = 4;
public const int Abbreviation = 3;
public const int Number = 2;
public const int Single = 1;
}
private static readonly Lazy<Month> InstanceFn =
new Lazy<Month>(() => new Month());
public static Month Instance { get { return InstanceFn.Value; } }
private Month() { }
public int Full { get { return As.Full; } }
public int Abbreviation { get { return As.Abbreviation; } }
public int Number { get { return As.Number; } }
public int Single { get { return As.Single; } }
}
public static DateFormat Date { get{return new DateFormat();}}
public static TimeFormat Time { get { return new TimeFormat(); } }
}
public class DateFormat
{
private readonly StringBuilder _value;
public TimeFormat Time
{
get
{
_value.Append(" ");
return new TimeFormat(_value);
}
}
public DateFormat(StringBuilder value = null)
{
_value = value ?? new StringBuilder();
}
public DateFormat And(string s = null)
{
_value.Append(s ?? "-");
return this;
}
public DateFormat Year(Func<F.Year, int> f)
{
return Year(f(F.Year.Instance));
}
public DateFormat Year(int i = 4)
{
_value.Append('y', i);
return this;
}
public DateFormat Month(Func<F.Month, int> f)
{
return Month(f(F.Month.Instance));
}
public DateFormat Month(int i = 2)
{
_value.Append('M', i);
return this;
}
public DateFormat Day(int i = 2)
{
_value.Append('d', i);
return this;
}
public static implicit operator string(DateFormat item)
{
return item._value.ToString();
}
public override string ToString()
{
return _value.ToString();
}
}
public class TimeFormat
{
private readonly StringBuilder _value;
public DateFormat Time
{
get
{
_value.Append(" ");
return new DateFormat(_value);
}
}
public TimeFormat(StringBuilder value = null)
{
_value = value ?? new StringBuilder();
}
public TimeFormat And(string s = null)
{
_value.Append(s ?? ":");
return this;
}
public TimeFormat Hour()
{
_value.Append("HH");
return this;
}
public TimeFormat Minute()
{
_value.Append("mm");
return this;
}
public static implicit operator string(TimeFormat item)
{
return item._value.ToString();
}
public override string ToString()
{
return _value.ToString();
}
}