Skip to content

Instantly share code, notes, and snippets.

@carolynvs
Created August 13, 2012 23:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carolynvs/3344800 to your computer and use it in GitHub Desktop.
Save carolynvs/3344800 to your computer and use it in GitHub Desktop.
Utility for dynamically converting all DateTime properties on an object to UTC
using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Objects;
using System.Linq;
using Carolynvs.Model; // Contains Carolynvs.UtcDateTimeConverter which provides UtcDateTimeConverter.Convert(object model)
namespace Carolynvs.DAL
{
public class MyDataContext : DbContext
{
public MyDataContext()
{
ObjectContext.ObjectMaterialized += ObjectMaterialized;
ObjectContext.SavingChanges += SavingChanges;
}
protected ObjectContext ObjectContext
{
get { return ((IObjectContextAdapter)this).ObjectContext; }
}
/// <summary>
/// Convert all DateTime properties on models saved to the database
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SavingChanges(object sender, EventArgs e)
{
var context = sender as ObjectContext;
if (context == null)
return;
foreach (ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
{
UtcDateTimeConverter.Convert(entry.Entity);
}
}
/// <summary>
/// Convert all DateTime properties on models retrieved from the database
/// </summary>
private void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
object model = e.Entity;
if (model == null)
return;
UtcDateTimeConverter.Convert(model);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Carolynvs.Extensions; // Contains Carolynvs.ObjectExtensions which provides object.Get<T>(string property) and object.Set(string property, T value)
namespace Carolynvs.Model
{
/// <summary>
/// Utility for converting DateTime properties to UTC
/// </summary>
public static class UtcDateTimeConverter
{
private static volatile object _lock = new object();
// Cache of the DateTime properties on each type
private static readonly Dictionary<Type, IEnumerable<PropertyInfo>> _typesWithDateTimeProperties = new Dictionary<Type, IEnumerable<PropertyInfo>>();
/// <summary>
/// Converts each DateTime property on the specified model to Utc
/// </summary>
public static void Convert(object model)
{
Type modelType = model.GetType();
IEnumerable<PropertyInfo> dateTimeProperties;
if (!_typesWithDateTimeProperties.ContainsKey(modelType))
{
lock(_lock)
{
if(!_typesWithDateTimeProperties.ContainsKey(modelType))
{
dateTimeProperties = modelType.GetProperties().Where(p => p.PropertyType.GetTypeFromNullable() == typeof(DateTime));
_typesWithDateTimeProperties.Add(modelType, dateTimeProperties);
}
}
}
dateTimeProperties = _typesWithDateTimeProperties[modelType];
foreach (PropertyInfo dateTimeProperty in dateTimeProperties)
{
DateTime? dateTime;
if (dateTimeProperty.PropertyType.IsGenericType)
{
dateTime = model.Get<DateTime?>(dateTimeProperty.Name);
}
else
{
dateTime = model.Get<DateTime>(dateTimeProperty.Name);
}
if (dateTime == null)
continue;
model.Set(dateTimeProperty.Name, ConvertToUtc(dateTime.Value));
}
}
/// <summary>
/// Converts a DateTime to Utc based on its DateTimeKind, Unspecified is assumed to be UTC
/// </summary>
public static DateTime ConvertToUtc(DateTime dateTime)
{
switch (dateTime.Kind)
{
case DateTimeKind.Unspecified:
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
case DateTimeKind.Local:
return dateTime.ToUniversalTime();
default:
return dateTime;
}
}
}
}
@carolynvs
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment