DSInternals/Src/Microsoft.Isam.Esent.Interop/jet_logtime.cs

234 lines
8.5 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="jet_logtime.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Isam.Esent.Interop
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
/// <summary>
/// Describes a date/time.
/// </summary>
[SuppressMessage(
"Microsoft.StyleCop.CSharp.NamingRules",
"SA1305:FieldNamesMustNotUseHungarianNotation",
Justification = "This should match the name of the unmanaged structure.")]
[StructLayout(LayoutKind.Sequential)]
[Serializable]
public partial struct JET_LOGTIME : IEquatable<JET_LOGTIME>, IJET_LOGTIME
{
/// <summary>
/// The time in seconds. This value can be 0 to 59.
/// </summary>
private readonly byte bSeconds;
/// <summary>
/// The time in minutes. This value can be 0 to 59.
/// </summary>
private readonly byte bMinutes;
/// <summary>
/// The time in hours. This value can be 0 to 23.
/// </summary>
private readonly byte bHours;
/// <summary>
/// The day of the month. This value can be 0 to 31. 0 is
/// used when the structure is null.
/// </summary>
private readonly byte bDays;
/// <summary>
/// The month. This value can be 0 to 12. 0 is
/// used when the structure is null.
/// </summary>
private readonly byte bMonth;
/// <summary>
/// The year of the event, offset by 1900.
/// </summary>
private readonly byte bYear;
/// <summary>
/// IsUTC flag at the first bit. Starting from win8, milli-seconds (low part) is filled at left 7 bits.
/// </summary>
private readonly byte bFiller1;
/// <summary>
/// OSSnapshot flag at the first bit, Starting from win8, milli-seconds (high part) is filled at following 3 bits. Other bits are reserved.
/// </summary>
private readonly byte bFiller2;
/// <summary>
/// Initializes a new instance of the <see cref="JET_LOGTIME"/> struct.
/// </summary>
/// <param name="time">
/// The DateTime to intialize the structure with.
/// </param>
internal JET_LOGTIME(DateTime time)
{
this.bSeconds = checked((byte)time.Second);
this.bMinutes = checked((byte)time.Minute);
this.bHours = checked((byte)time.Hour);
this.bDays = checked((byte)time.Day);
this.bMonth = checked((byte)time.Month);
this.bYear = checked((byte)(time.Year - 1900));
// bFiller1: fTimeIsUTC at the first bit, bMillisecondsLow at left 7 bits
this.bFiller1 = (time.Kind == DateTimeKind.Utc) ? (byte)0x1 : (byte)0;
this.bFiller1 |= checked((byte)((time.Millisecond & 0x7F) << 1));
// bFiller2: fOSSnapshot at the first bit, bMillisecondsHigh at following 3 bits
this.bFiller2 = checked((byte)((time.Millisecond & 0x380) >> 6));
}
/// <summary>
/// Gets a value indicating whether the JET_LOGTIME has a null value.
/// </summary>
public bool HasValue
{
get { return 0 != this.bMonth && 0 != this.bDays; }
}
/// <summary>
/// Gets a value indicating whether the JET_LOGTIME is in UTC.
/// </summary>
[SuppressMessage(
"Microsoft.StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "This should match the unmanaged API, which isn't capitalized.")]
public bool fTimeIsUTC
{
get { return 0 != (this.bFiller1 & 0x1); }
}
/// <summary>
/// Determines whether two specified instances of JET_LOGTIME
/// are equal.
/// </summary>
/// <param name="lhs">The first instance to compare.</param>
/// <param name="rhs">The second instance to compare.</param>
/// <returns>True if the two instances are equal.</returns>
public static bool operator ==(JET_LOGTIME lhs, JET_LOGTIME rhs)
{
return lhs.Equals(rhs);
}
/// <summary>
/// Determines whether two specified instances of JET_LOGTIME
/// are not equal.
/// </summary>
/// <param name="lhs">The first instance to compare.</param>
/// <param name="rhs">The second instance to compare.</param>
/// <returns>True if the two instances are not equal.</returns>
public static bool operator !=(JET_LOGTIME lhs, JET_LOGTIME rhs)
{
return !(lhs == rhs);
}
/// <summary>
/// Generate a DateTime representation of this JET_LOGTIME.
/// </summary>
/// <returns>
/// A DateTime representing the JET_LOGTIME. If the JET_LOGTIME
/// is null then null is returned.
/// </returns>
public DateTime? ToDateTime()
{
if (!this.HasValue)
{
return null;
}
return new DateTime(
this.bYear + 1900,
this.bMonth,
this.bDays,
this.bHours,
this.bMinutes,
this.bSeconds,
checked((int)((((uint)this.bFiller2 & 0xE) << 6) | (((uint)this.bFiller1 & 0xFE) >> 1))),
this.fTimeIsUTC ? DateTimeKind.Utc : DateTimeKind.Local);
}
/// <summary>
/// Generate a string representation of the structure.
/// </summary>
/// <returns>The structure as a string.</returns>
public override string ToString()
{
return string.Format(
CultureInfo.InvariantCulture,
"JET_LOGTIME({0}:{1}:{2}:{3}:{4}:{5}:0x{6:x}:0x{7:x})",
this.bSeconds,
this.bMinutes,
this.bHours,
this.bDays,
this.bMonth,
this.bYear,
this.bFiller1,
this.bFiller2);
}
/// <summary>
/// Returns a value indicating whether this instance is equal
/// to another instance.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>True if the two instances are equal.</returns>
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return this.Equals((JET_LOGTIME)obj);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode()
{
// None of the members are larger than a byte and many use fewer than
// all 8 bits (e.g. a month count uses only 4 bits). Spread the members
// out through the 32-bit hash value.
// (This is better than the default implementation of GetHashCode, which
// easily aliases different JET_LOGTIMES to the same hash code)
return this.bSeconds.GetHashCode()
^ (this.bMinutes << 6)
^ (this.bHours << 12)
^ (this.bDays << 17)
^ (this.bMonth << 22)
^ (this.bYear << 24)
^ this.bFiller1
^ (this.bFiller2 << 8);
}
/// <summary>
/// Returns a value indicating whether this instance is equal
/// to another instance.
/// </summary>
/// <param name="other">An instance to compare with this instance.</param>
/// <returns>True if the two instances are equal.</returns>
public bool Equals(JET_LOGTIME other)
{
return this.bSeconds == other.bSeconds
&& this.bMinutes == other.bMinutes
&& this.bHours == other.bHours
&& this.bDays == other.bDays
&& this.bMonth == other.bMonth
&& this.bYear == other.bYear
&& this.bFiller1 == other.bFiller1
&& this.bFiller2 == other.bFiller2;
}
}
}