Thursday, September 18, 2008

Converting from one time zone to another in ASP.NET

Often while developing web applications we come across problem showing date time in diffrent time zones. for example if a webserver is located in US and users use application elsewhere in the globe so it becomes difficult to to keep track of things as to when they entered particular information (Audit values). One solution is to save all dates in database in GMT time and then while showing dates to users convert dates from GMT to users local time zone. we can have users submit their time zone information while registering users for the site. The following class shows methods that convert time from one time zone to another. One can use these methods and customise their code according to thier business logic.


namespace eCRF.Utility {
///
/// Used to convert to/from utc times and local times and respect DST.
/// Can also covert between two local time zones.
/// Information about a time zone containing methods to convert local times to and from UTC and
/// between local time zones.
///
[Serializable]
public class TimeZoneInformation {#region Fields
private TZI tzi; // Current time zone information.
private string displayName; // Current time zone display name.
private string standardName; // Current time zone standard name (non-DST).
private string daylightName; // Current time zone daylight name (DST).
private static readonly List timeZones; // static list of all time zones on machine.
#endregion#region Constructors
public TimeZoneInformation() {}
static TimeZoneInformation() {
timeZones = new List();
using(RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones")) {
string[] zoneNames = key.GetSubKeyNames();
foreach(string zoneName in zoneNames) {
using(RegistryKey subKey = key.OpenSubKey(zoneName)) {
TimeZoneInformation tzi = new TimeZoneInformation();
tzi.displayName = (string) subKey.GetValue("Display");
tzi.standardName = (string) subKey.GetValue("Std");
tzi.daylightName = (string) subKey.GetValue("Dlt");
tzi.InitTzi((byte[]) subKey.GetValue("Tzi"));
timeZones.Add(tzi);
}
}
}
}#endregion#region Public Properties
///
/// Gets list of all time zones defined on the current computer system.
///
public static List TimeZones {
get {
// Return a copy of the list.
List nList = new List(timeZones);
return nList;
}
}
///
/// Gets an string array of standard time zone names supported on the current system.
///
public static string[] TimeZoneNames {
get {
List list = new List();
foreach(TimeZoneInformation tzi in timeZones) {
list.Add(tzi.StandardName);
}
return list.ToArray();
}
}
///
/// Gets the time zone information of the current computer system.
///
public static TimeZoneInformation CurrentTimeZone {
get {
string tzn = TimeZone.CurrentTimeZone.StandardName;
TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(tzn);
return tzi;
}
}
///
/// The time zone's name during 'standard' time (i.e. not daylight savings).
///
public string StandardName {
get {
return standardName;
}
}
///
/// The time zone's name during daylight savings time (DST).
///
public string DaylightName {
get {
return daylightName;
}
}
///
/// The time zone's display name (e.g. "(GMT-05:00) Eastern Time (US and Canada)").
///
public string DisplayName {
get {
return displayName;
}
}
///
/// Gets the standard offset from UTC as a TimeSpan.
///
public TimeSpan StandardOffset {
get {
return TimeSpan.FromMinutes(StandardBias);
}
}
///
/// Gets the daylight offset from UTC as a TimeSpan.
///
public TimeSpan DaylightOffset {
get {
return TimeSpan.FromMinutes(DaylightBias);
}
}
///
/// Gets the difference, in minutes, between UTC and local time.
/// UTC = local time + bias.
///
public int StandardBias {
get {
return - (tzi.bias + tzi.standardBias);
}
}
///
/// Gets the difference, in minutes, between UTC and local time (in daylight savings time).
/// UTC = local time + bias.
///
public int DaylightBias {
get {
return - (tzi.bias + tzi.daylightBias);
}
}#endregion#region Public Methods
///
/// Returns standard name of this time zone instance.
///
/// Time zone standard name.
public override string ToString() {
return this.standardName;
}
///
/// Returns a TimeZoneInformation instance for the time zone with supplied standard name.
///
/// Standard name of the time zone.
/// TimeZoneInformation instance.
/// Thrown if name not found.
public static TimeZoneInformation GetTimeZone(string standardTimeZoneName) {
if (standardTimeZoneName == null) standardTimeZoneName = ".";
if (standardTimeZoneName == ".") standardTimeZoneName = TimeZone.CurrentTimeZone.StandardName;
foreach(TimeZoneInformation tzi in TimeZoneInformation.TimeZones) {
if (tzi.StandardName.Equals(standardTimeZoneName, StringComparison.OrdinalIgnoreCase)) return tzi;
}
throw new ArgumentException("standardTimeZoneName not found.");
}
///
/// Converts the value of the utc time to a local time in this time zone.
///
/// The UTC time to convert.
/// The local time.
public DateTime ToLocalTime(DateTime utc) {
// Convert to SYSTEMTIME
SYSTEMTIME stUTC = DateTimeToSystemTime(utc);
// Set up the TIME_ZONE_INFORMATION
TIME_ZONE_INFORMATION tziNative = TziNative();
SYSTEMTIME stLocal;
NativeMethods.SystemTimeToTzSpecificLocalTime(ref tziNative, ref stUTC, out stLocal);
// Convert back to DateTime
return SystemTimeToDateTime(ref stLocal);
}
///
/// Converts the value of the utc time to local time in supplied time zone.
///
/// The time to convert.
/// The standard name of the time zone.
/// The local time.
/// Thrown if time zone not found.
public static DateTime ToLocalTime(DateTime utc, string targetTimeZoneName) {
TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(targetTimeZoneName);
return tzi.ToLocalTime(utc);
}
///
/// Converts a localTime from a source time zone to a target time zone, adjusting for DST as needed.
/// The localTime must be a local time in the sourceTimeZoneName time zone.
///
/// Time zone name which represents localTime.
/// The source local time.
/// The time zone name which to convert the localTime.
/// The local time for targetTimeZoneName.
public static DateTime ToLocalTime(string sourceTimeZoneName, DateTime localTime, string targetTimeZoneName) {
DateTime utc = TimeZoneInformation.ToUniversalTime(sourceTimeZoneName, localTime);
DateTime lt = TimeZoneInformation.ToLocalTime(utc, targetTimeZoneName);
return lt;
}
///
/// Converts the value of the local time to UTC time.
/// Note that there may be different possible interpretations at the daylight time boundaries.
///
/// The local time to convert.
/// The UTC DateTime.
/// Thrown if the method failed due to missing platform support.
public DateTime ToUniversalTime(DateTime local) {
SYSTEMTIME stLocal = DateTimeToSystemTime(local);
TIME_ZONE_INFORMATION tziNative = TziNative();
SYSTEMTIME stUTC;
try {
NativeMethods.TzSpecificLocalTimeToSystemTime(ref tziNative, ref stLocal, out stUTC);
return SystemTimeToDateTime(ref stUTC);
}
catch(EntryPointNotFoundException e) {
throw new NotSupportedException("This method is not supported on this operating system", e);
}
}
///
/// Converts a local time in specified time zone to UTC time.
///
/// The standard time zone name.
/// The local time to convert.
/// The UTC time.
/// Thrown if time zone name not found.
/// Thrown if the method failed due to missing platform support.
public static DateTime ToUniversalTime(string standardTimeZoneName, DateTime local) {
TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(standardTimeZoneName);
return tzi.ToUniversalTime(local);
}#endregion#region Private Methods
private static SYSTEMTIME DateTimeToSystemTime(DateTime dt) {
SYSTEMTIME st;
FILETIME ft = new FILETIME();
ft.dwHighDateTime = (int)(dt.Ticks >> 32);
ft.dwLowDateTime = (int)(dt.Ticks & 0xFFFFFFFFL);
NativeMethods.FileTimeToSystemTime(ref ft, out st);
return st;
}
private static DateTime SystemTimeToDateTime(ref SYSTEMTIME st) {
FILETIME ft = new FILETIME();
NativeMethods.SystemTimeToFileTime(ref st, out ft);
DateTime dt = new DateTime((((long) ft.dwHighDateTime) << tzinative = " new"
bias = " tzi.bias;"
standarddate = " tzi.standardDate;"
standardbias = " tzi.standardBias;"
daylightdate = " tzi.daylightDate;"
daylightbias = " tzi.daylightBias;" >
/// The standard Windows SYSTEMTIME structure.
///
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEMTIME {
public UInt16 wYear;
public UInt16 wMonth;
public UInt16 wDayOfWeek;
public UInt16 wDay;
public UInt16 wHour;
public UInt16 wMinute;
public UInt16 wSecond;
public UInt16 wMilliseconds;
}
// FILETIME is already declared in System.Runtime.InteropServices.
///
/// The layout of the Tzi value in the registry.
///
[StructLayout(LayoutKind.Sequential)]
private struct TZI {
public int bias;
public int standardBias;
public int daylightBias;
public SYSTEMTIME standardDate;
public SYSTEMTIME daylightDate;
}
///
/// The standard Win32 TIME_ZONE_INFORMATION structure.
/// Thanks to www.pinvoke.net.
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct TIME_ZONE_INFORMATION {
[MarshalAs(UnmanagedType.I4)]
public Int32 Bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string StandardName;
public SYSTEMTIME StandardDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 StandardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DaylightName;
public SYSTEMTIME DaylightDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 DaylightBias;
}
///
/// A container for P/Invoke declarations.
///
private struct NativeMethods {
private const string KERNEL32 = "kernel32.dll";
[DllImport(KERNEL32)]
public static extern uint GetTimeZoneInformation(out TIME_ZONE_INFORMATION
lpTimeZoneInformation);
[DllImport(KERNEL32)]
public static extern bool SystemTimeToTzSpecificLocalTime([In] ref TIME_ZONE_INFORMATION lpTimeZone, [In] ref SYSTEMTIME lpUniversalTime, out SYSTEMTIME lpLocalTime);
[DllImport(KERNEL32)]
public static extern bool SystemTimeToFileTime([In] ref SYSTEMTIME lpSystemTime, out FILETIME lpFileTime);
[DllImport(KERNEL32)]
public static extern bool FileTimeToSystemTime([In] ref FILETIME lpFileTime, out SYSTEMTIME lpSystemTime);
///
/// Convert a local time to UTC, using the supplied time zone information.
/// Windows XP and Server 2003 and later only.
///
/// The time zone to use.
/// The local time to convert.
/// The resultant time in UTC.
/// true if successful, false otherwise.
[DllImport(KERNEL32)]
public static extern bool TzSpecificLocalTimeToSystemTime([In] ref TIME_ZONE_INFORMATION lpTimeZone, [In] ref SYSTEMTIME lpLocalTime, out SYSTEMTIME lpUniversalTime);
}
///
/// Initialise the m_tzi member.
///
/// The Tzi data from the registry.
private void InitTzi(byte[] info) {
if (info.Length != Marshal.SizeOf(tzi)) throw new ArgumentException("Information size is incorrect", "info");
// Could have sworn there's a Marshal operation to pack bytes into
// a structure, but I can't see it. Do it manually.
GCHandle h = GCHandle.Alloc(info, GCHandleType.Pinned);
try {
tzi = (TZI) Marshal.PtrToStructure(h.AddrOfPinnedObject(), typeof(TZI));
}
finally {
h.Free();
}
}#endregion
}
}

Adding Sorting image (up down arrow) while sorting grid view asp.net 2.0

This article shows code how to show toggle image according to sort direction while gridview sorting.


//save column name in a view state
Protected Sub gvContentList_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gvContentList.Sorting


ViewState.Add("colname", e.SortExpression)


End Sub



Protected Sub gvContentList_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvContentList.RowCreated
Dim defaultsortimage As New Image
defaultsortimage.ImageUrl = "~/images/tbl_ascend_ord.gif"
If e.Row.RowType = DataControlRowType.Header Then
If ViewState("exp") <> "" Then
AddSortImage(e.Row)
Else
e.Row.Cells(0).Controls.Add(defaultsortimage)
End If
End If
End Sub





Public Sub AddSortImage(ByVal headerrow As GridViewRow)
Dim nColumnindex As Integer
Dim sortimage As New Image
Dim sortdirection As String
nColumnindex = getsortcolumnindex(ViewState("colname").ToString())
sortdirection = ViewState("colname").ToString + ".asc"
If ViewState("exp") = sortdirection Then
'sortimage.ImageUrl = "~/images/tbl_ascend_ord.gif"
headerrow.Cells(nColumnindex).CssClass = "sortascheaderstyle"
Else
'sortimage.ImageUrl = "~/images/tbl_descend_ord.gif"
headerrow.Cells(nColumnindex).CssClass = "sortdescheaderstyle"
End If
End Sub


Public Function getsortcolumnindex(ByVal strcol As String)
For Each field As DataControlField In gvContentList.Columns
If field.SortExpression = strcol Then
Return gvContentList.Columns.IndexOf(field)
End If

Next
Return -1
End Function

Thursday, September 11, 2008

Sorting a GridView Using IComparer Interface

Sorting using IComparer Interface using

Implement a Generic Comparer class as below.

public class GenericComparer: IComparer {
private SortDirection _sortdirection;
private string _sortexpression;
private string _sortorder;
public SortDirection sortdirection {
get {
return _sortdirection;
}
set {
_sortdirection = value;
}
}
public string sortexpression {
get {
return _sortexpression;
}
set {
_sortexpression = value;
}
}
public string sortorder {
get {
return _sortorder;
}
set {
_sortorder = value;
}
}
public GenericComparer(string sortexpression, SortDirection sortdirection, string sortorder) {
this.sortexpression = sortexpression;
this.sortdirection = sortdirection;
this.sortorder = sortorder;
}#region IComparer Members
public int Compare(T x, T y) {
PropertyInfo propertyinfo;
IComparable obj1;
IComparable obj2;
string direc;
string strStart;
string strEnd;
propertyinfo = typeof(T).GetProperty(sortexpression);
obj1 = (IComparable) propertyinfo.GetValue(x, null);
obj2 = (IComparable) propertyinfo.GetValue(y, null);
if (sortorder.EndsWith("asc")) {
return obj1.CompareTo(obj2);
}
else {
return obj2.CompareTo(obj1);
}
}#endregion
}

Now write the follwing code in grid 's sorting event.


protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ViewState.Add("exp", "");

}

}


protected void grvLstFtpFiles_Sorting(object sender, GridViewSortEventArgs e)
{
BusinessObjects.ViewUploadedFilesCollection oViewUploadedFilesCol = new BusinessObjects.ViewUploadedFilesCollection();
oViewUploadedFilesCol.Query.Where(oViewUploadedFilesCol.Query.NTrialId.Equal(ddlTrials.SelectedValue));
oViewUploadedFilesCol.Query.OrderBy(oViewUploadedFilesCol.Query.DCreatedDt.Descending);
oViewUploadedFilesCol.Query.Load();
string sortorder;
ViewState.Add("colname", e.SortExpression);
if ( ViewState["exp"] == "")
{
ViewState["exp"] = e.SortExpression.ToString() + ".asc";
}
else if ( ViewState["exp"].ToString() == e.SortExpression.ToString() + ".asc")
{
ViewState["exp"] = e.SortExpression.ToString() + ".dsc";
}
else
{
ViewState["exp"] = e.SortExpression.ToString() + ".asc";
}
sortorder = ViewState["exp"].ToString();
GenericComparer comp = new GenericComparer(e.SortExpression, e.SortDirection, sortorder);
System.Collections.Generic.List list = (System.Collections.Generic.List)oViewUploadedFilesCol;
//list.Sort(comp);
list.Sort(new GenericComparer(e.SortExpression, e.SortDirection, sortorder));
grvLstFtpFiles.DataSource = list;
grvLstFtpFiles.DataBind();
}

This sorting method can be used used when binding gridview with a collection of objects, i have used this code to bind a grid view with entity spaces collection object. This method can be useful when one uses object datasource to bind a grid.

In the above code oViewUploadedFilesCol is a collection of objects of type '
BusinessObjects.ViewUploadedFiles ''