tick() method in a digital clock - c# - c#

For my assignment, we are supposed to create a digital clock. I've been stuck at the 3rd part of the question for a while.
Here's the question :
write a Clock class to represent a single clock. You can have hours, minutes and seconds as instance variables.You can add a method to print time, assuming it is a digital clock.
write test class ClockTester and try to create clocks to represent different countries, Print their time.
Add the below methods to make the clock working better.
tick() – it will represent one tick of the clock.
incrementSeconds() - It will increase the time by 1 second.
incrementMinutes() - It will increase the time by 1 minute.
incrementHours() - It will increase the time by 1 hour.
Here's the code I tried, It does print the time of the countries but the tick method does not increment the time. -
Clock class:
public class Clock
{
//instance variables
private int hours, minutes, seconds;
public Clock()
{
SetTime(0, 0, 0);
}
public Clock(int hours, int minutes, int seconds)
{
SetTime(hours, minutes, seconds);
}
public void SetTime(int hours, int minutes, int seconds)
{
if ((seconds >= 0) && (seconds < 60) && (minutes >= 0) && (minutes < 60)
&& (hours >= 0) && (hours < 24)) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
else
{
this.hours = 0;
this.minutes = 0;
this.seconds = 0;
}
}
public int GetHours()
{
return hours;
}
public int GetMinutes()
{
return minutes;
}
public int GetSeconds()
{
return seconds;
}
//Tick()
public void Tick()
{
IncrementSeconds();
IncrementMinutes();
IncrementHours();
}
//incrementSeconds()
public void IncrementSeconds()
{
seconds++;
if (seconds > 59)
{
seconds = 0;
IncrementMinutes();
}
}
//incrementMinutes()
public void IncrementMinutes()
{
minutes++;
if (minutes > 59)
{
minutes = 0;
IncrementHours();
}
}
//incrementHours()
public void IncrementHours()
{
hours++;
if (hours > 23)
{
hours = 0;
}
}
}
clockTester class :
public class ClockTester
{
public static void Main(string[] args)
{
//print time in UK - London
Clock clockUK = new Clock();
clockUK.SetTime(18, 29, 48);
Console.WriteLine("London, UK : {0}:{1}:{2}", clockUK.GetHours(), clockUK.GetMinutes(), clockSL.GetSeconds());
//print time in US - New York
Clock clockUS = new Clock();
clockUS.SetTime(13, 29, 48);
Console.WriteLine("New York, US : {0}:{1}:{2}", clockUS.GetHours(), clockUS.GetMinutes(), clockUS.GetSeconds());
//print time in Japan - Tokyo
Clock clockJP = new Clock();
clockJP.SetTime(02, 29, 48);
Console.WriteLine("Tokyo, Japan : {0}:{1}:{2}", clockJP.GetHours(), clockJP.GetMinutes(), clockJP.GetSeconds());
}
}

You should have heard of the ToString method/function.
All objects have one in C# because all classes inherit/descend from Object class which defines a tostring method https://learn.microsoft.com/en-us/dotnet/api/system.object.tostring?view=netframework-4.8 and you can overload the default with your own implementation.
https://learn.microsoft.com/en-us/dotnet/api/system.object.tostring?view=netframework-4.8#overloading-the-tostring-method
Your ToString function should return a formatted string, look at https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings and https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings
e.g.
public class MyTimeClass {
// fields/variables/properties and other methods not displayed, use imagination!
public string ToString(){
return String.Format("{0:00}:{1:00}:{2:00}.{3:000}",this.hours, this.minutes, this.seconds, this.ticks);
//ideally this would be culture dependant/sensitive
}
}
https://dotnetfiddle.net/uN2H2F

Related

My "Time" class is stuck with the default data I set for hours, minutes and seconds, can't change their values by any means

My homework assignment asks me to make a class called "Time". When I initialize two instances of the class, where one assigns the hours, minutes, and seconds randomly, and where the other one gets it's input from the parameters, it seems like both instances are stuck at the default "0:0:0".
This is the class:
class Time
{
private static int hours = 0;
private static int minutes = 0;
private static int seconds = 0;
public static int Hours
{
get { return hours; }
set { hours = (Hours > -1 && Hours < 24) ? Hours : 0; }
}
public static int Minutes
{
get { return minutes; }
set { minutes = (Minutes > -1 && Minutes < 24) ? Minutes : 0; }
}
public static int Seconds
{
get { return seconds; }
set { seconds = (Seconds > -1 && Seconds < 24) ? Seconds : 0; }
}
public Time()
{
Random rand = new Random();
Hours = rand.Next(-1, 24);
Minutes = rand.Next(-1, 60);
Seconds = rand.Next(-1, 60);
}
public Time(int hour, int minute, int second)
{
Hours = hour;
Minutes = minute;
Seconds = second;
}
public string Show()
{
return $"{hours}:{minutes}:{seconds}";
}
}
This is the code in the Main method:
static void Main(string[] args)
{
var T1 = new Time();
var T2 = new Time(12, 24, 48);
Console.WriteLine(T1.Show());
Console.WriteLine(T2.Show());
Console.ReadKey();
}
I've tried everything but nothing worked, maybe only I don't see the problem.
Several problems:
Don't use static here. Static means same for every instance
Don't initialize your random hours, minutes and seconds with rand.Next(-1, 24) but rand.Next(0, 24)
The setters are wrong:
set { hours = (Hours > -1 && Hours < 24) ? Hours : 0; }
You have to use value instead of Hours(same with other properties).
Static means that every new Time will have the same data, and changing it for one instance of Time changes it for all. Remove static from your field and property references, and it should work.

Find Next Recurring Date Based on a Schedule

Let's say I need to find out when the next scheduled date is when I know that the schedule was based off a start date of 8/1/2014, it's supposed to run every 7 days and the current date is 8/10/2014. I should get back a date of 8/14/2014. I eventually want to make this code work for every X hours, days, and weeks, bur right now I'm just testing with days. I have the following code I'm using to calculate the next run time, but I get it to work for one date and then it fails for another. FYI, I'm using the option to specify the current date for testing purposes. What am I doing wrong?
public class ScheduleComputer
{
public DateTime GetNextRunTime(ScheduleRequest request)
{
var daysSinceBase = ((int)((request.CurrentDate - request.BaseDate).TotalDays)) + 1;
var partialIntervalsSinceBaseDate = daysSinceBase % request.Interval;
var fullIntervalsSinceBaseDate = daysSinceBase / request.Interval;
var daysToNextRun = 0;
if (partialIntervalsSinceBaseDate > 0)
{
daysToNextRun = (request.Interval - partialIntervalsSinceBaseDate) + 1;
}
var nextRunDate = request.BaseDate.AddDays((fullIntervalsSinceBaseDate * request.Interval) + daysToNextRun - 1);
return nextRunDate;
}
}
public class ScheduleRequest
{
private readonly DateTime _currentDate;
public ScheduleRequest()
{
_currentDate = DateTime.Now;
}
public ScheduleRequest(DateTime currentDate)
{
_currentDate = currentDate;
}
public DateTime CurrentDate
{
get { return _currentDate; }
}
public DateTime BaseDate { get; set; }
public Schedule Schedule { get; set; }
public int Interval { get; set; }
}
public enum Schedule
{
Hourly,
Daily,
Weekly
}
And here are my unit tests
[TestFixture]
public class ScheduleComputerTests
{
private ScheduleComputer _scheduleComputer;
[SetUp]
public void SetUp()
{
_scheduleComputer = new ScheduleComputer();
}
[Test]
public void ThisTestPassesAndItShould()
{
var scheduleRequest = new ScheduleRequest(currentDate: DateTime.Parse("8/14/2014"))
{
BaseDate = DateTime.Parse("8/1/2014"),
Schedule = Schedule.Daily,
Interval = 7
};
var result = _scheduleComputer.GetNextRunTime(scheduleRequest);
Assert.AreEqual(DateTime.Parse("8/14/2014"), result);
}
[Test]
public void ThisTestFailsAndItShouldNot()
{
var scheduleRequest = new ScheduleRequest(currentDate: DateTime.Parse("8/2/2014"))
{
BaseDate = DateTime.Parse("8/1/2014"),
Schedule = Schedule.Daily,
Interval = 7
};
var result = _scheduleComputer.GetNextRunTime(scheduleRequest);
Assert.AreEqual(DateTime.Parse("8/7/2014"), result);
}
FYI, I saw the post here, but I can't seem to tailor it to my needs.
--- UPDATE 1 ---
Here is my updated code. I know I've made it verbose with variables so I can understand the logic better (hopefully that doesn't impact performance much). I also added logic to deal with different periods (hours, days, weeks) and added extension methods to make the code somewhat cleaner. However, this code seems to be working perfectly for hours and days, but is failing on weeks. Somewhere I'm not multiplying or dividing by 7 properly.
public class ScheduleComputer
{
public DateTime GetNextRunTime(ScheduleRequest request)
{
var timeBetwenCurrentAndBase = request.CurrentDate - request.BaseDate;
var totalPeriodsBetwenCurrentAndBase = timeBetwenCurrentAndBase.TotalPeriods(request.Schedule);
var fractionalIntervals = totalPeriodsBetwenCurrentAndBase % request.Interval;
var partialIntervalsLeft = request.Interval - fractionalIntervals;
if (request.Schedule != Schedule.Hourly) partialIntervalsLeft = partialIntervalsLeft - 1;
var nextRunTime = request.CurrentDate.AddPeriods(partialIntervalsLeft, request.Schedule);
return nextRunTime;
}
}
public static class ScheduleComputerExtensions
{
public static double TotalPeriods(this TimeSpan timeBetwenCurrentAndBase, Schedule schedule)
{
switch (schedule)
{
case Schedule.Hourly: return timeBetwenCurrentAndBase.TotalHours;
case Schedule.Daily: return timeBetwenCurrentAndBase.TotalDays;
case Schedule.Weekly: return timeBetwenCurrentAndBase.TotalDays * 7;
default: throw new ApplicationException("Invalid Schedule Provided");
}
}
public static DateTime AddPeriods(this DateTime dateTime, double partialIntervalsLeft, Schedule schedule)
{
switch (schedule)
{
case Schedule.Hourly: return dateTime.AddHours(partialIntervalsLeft);
case Schedule.Daily: return dateTime.AddDays(partialIntervalsLeft);
case Schedule.Weekly: return dateTime.AddDays(partialIntervalsLeft * 7);
default: throw new ApplicationException("Invalid Schedule Provided");
}
}
}
Try replacing your GetNextRunTime with this
public DateTime GetNextRunTime(ScheduleRequest request)
{
double days = (request.Interval - ((request.CurrentDate - request.BaseDate).TotalDays % request.Interval));
return request.CurrentDate.AddDays(days-1);
}
That should give you the correct dates.
EDIT: Let's break it down in hopes of helping you figure out the logic.
diff = (request.CurrentDate - request.BaseDate).TotalDays this gives you the number of days between the BaseDate and CurrentDate. Note that the number of days DOES NOT INCLUDE the day for BaseDate. So the different between 8/7/14 and 8/1/14 is 6 days.
daysSinceLast = diff % request.Interval this gives you the number of days that have past since the last interval hit, so if the last interval hit on 8/1/14 and it is now 8/7/14 then the result would be 6 % 7 = 6; 6 days have past since the last scheduled interval (not including the last interval date). This is the most important part of the calculation; It keeps the number of days, no matter how many have passed within the interval, so for example, if 100 days have passed since the BaseDate and the interval is 7: 100 % 7 = 2 which means that 2 days have passed since the last interval triggered, there is no need to actually know the last date it was triggered. All you need is the BaseDate and CurrentDate. You could use this logic to find the date of the last triggered interval, just subtract the number of days from the CurrentDate.
daysUntil = request.Interval - daysSinceLast This gives you the number of days until the next scheduled interval. 7 - 6 = 1 day until the next scheduled interval
1 day in this scenario is not correct and the result will never be correct because the calculation of TimeSpan differences does not include the day for BaseDate, so you need to subtract 1 from the daysUntil nextDate = request.CurrentDate.AddDays(daysUntil - 1)
Adding the number of remaining days (minus 1 for the base date) to the current date gives you the required value. Does this help at all?
UPDATE
In light of your testing, I see that the problem is on both of our ends. My calculation was incorrect and you were multiplying by 7 when you needed to divide by 7. Either way, the result was still wrong. Try this instead.
Remove your extension class completely
Modify your GetNextRunTime with the below code
Modify your ScheduleRequest and Schedule class/enum with the below code
GetNextRunTime
public DateTime GetNextRunTime(ScheduleRequest request)
{
double diffMillis = (request.CurrentDate - request.BaseDate).TotalMilliseconds;
double modMillis = (diffMillis % request.IntervalMillis);
double timeLeft = (request.IntervalMillis - modMillis);
ulong adjust = (request.Schedule == Schedule.Daily) ? (ulong)Schedule.Daily : 0;
return request.CurrentDate.AddMilliseconds(timeLeft - adjust);
}
ScheduleRequest
public class ScheduleRequest
{
private readonly DateTime _currentDate;
public ScheduleRequest()
{
_currentDate = DateTime.Now;
}
public ScheduleRequest(DateTime currentDate)
{
_currentDate = currentDate;
}
public DateTime CurrentDate
{
get { return _currentDate; }
}
public DateTime BaseDate { get; set; }
public Schedule Schedule { get; set; }
public double IntervalMillis { get { return (double)this.Schedule * this.Interval; } }
public int Interval { get; set; }
}
Schedule
public enum Schedule : ulong
{
Hourly = 3600000,
Daily = 86400000,
Weekly = 604800000
}
This should work correctly for all dates, intervals and schedules. EDIT: corrected adjust value

Calculating total night time from timespan

Suppose night time is set from 20.30h till 6.15h(AM). These 2 parameters are user-scoped variables.
Suppose you have an arrival date and a departure date which can span from a few minutes to more than one total day.
How do you calculate the total hours of night time?
public static double CalculateTotalNightTimeHours(DateTime arrival,
DateTime departure,
int nightTimeStartHour,
int nightTimeStartMinute,
int nightTimeEndHour,
int nightTimeEndMinute)
{
//??
}
EDIT: I understand this may be no straight forward yes/no answer, but maybe someone has an elegant solution for this problem.
To answer the comments : I indeed want to calculate the total number of hours (or minutes) that fall between a user-editable night start and end time. I'm calculating visit time, and the first date is indeed the arrival parameter.
The code I had sofar :
DateTime nightStart = new DateTime( departure.Year, departure.Month, departure.Day,
nightTimeStartHour, nightTimeStartMinute, 0);
DateTime nightEnd = new DateTime( arrival.Year, arrival.Month, arrival.Day,
nightTimeEndHour, nightTimeEndMinute, 0);
if (arrival < nightEnd)
{
decimal totalHoursNight = (decimal)nightEnd.Subtract(arrival).TotalHours;
}
//...
Just because I was up for the challenge you should be able to use the following function with success. Please note that this is probably not the most efficient way to do it, but I did it this way so I could lay out the logic. I may decide to edit this as some point to improve it, but it should work fine as is.
It is also important to note a couple of assumptions here:
the 'end' parameter is always greater than the 'start' parameter (although we check that first thing anyway)
the night end parameters are earlier than the night start parameters (i.e. night time ends on the following day, but never as much as 24 hours later)
Daylight savings time does not exist! (this is a tricky concern, one important question to address is: if either your start or end time is at 01:30 on the day the clocks go back, how will you know if the time was recorded before or after the rollback? i.e is it the first or second time the clock has hit 01:30?)
with that in mind...
public static double Calc(DateTime start, DateTime end, int startHour, int startMin, int endHour, int endMin)
{
if (start > end)
throw new Exception();//or whatever you want to do
//create timespans for night hours
TimeSpan nightStart = new TimeSpan(startHour, startMin, 0);
TimeSpan nightEnd = new TimeSpan(endHour, endMin, 0);
//check to see if any overlapping actually happens
if (start.Date == end.Date && start.TimeOfDay >= nightEnd && end.TimeOfDay <= nightStart)
{
//no overlapping occurs so return 0
return 0;
}
//check if same day as will process this differently
if (start.Date == end.Date)
{
if (start.TimeOfDay > nightStart || end.TimeOfDay < nightEnd)
{
return (end - start).TotalHours;
}
double total = 0;
if (start.TimeOfDay < nightEnd)
{
total += (nightEnd - start.TimeOfDay).TotalHours;
}
if(end.TimeOfDay > nightStart)
{
total += (end.TimeOfDay - nightStart).TotalHours;
}
return total;
}
else//spans multiple days
{
double total = 0;
//add up first day
if (start.TimeOfDay < nightEnd)
{
total += (nightEnd - start.TimeOfDay).TotalHours;
}
if (start.TimeOfDay < nightStart)
{
total += ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours;
}
else
{
total += ((new TimeSpan(24, 0, 0)) - start.TimeOfDay).TotalHours;
}
//add up the last day
if (end.TimeOfDay > nightStart)
{
total += (end.TimeOfDay - nightStart).TotalHours;
}
if (end.TimeOfDay > nightEnd)
{
total += nightEnd.TotalHours;
}
else
{
total += end.TimeOfDay.TotalHours;
}
//add up any full days
int numberOfFullDays = (end - start).Days;
if (end.TimeOfDay > start.TimeOfDay)
{
numberOfFullDays--;
}
if (numberOfFullDays > 0)
{
double hoursInFullDay = ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours + nightEnd.TotalHours;
total += hoursInFullDay * numberOfFullDays;
}
return total;
}
}
You can then call it something like this:
double result = Calc(startDateTime, endDateTime, 20, 30, 6, 15);
Basically you'll want to calculate when night starts and ends. Then compare those to the arrival and departure dates to see if you arrival after night starts or depart before it ends to get the values you need to subtract to determine the total night hours. Then you need to continue to calculate this for each day until the start time for night is pass the departure date. Here's my solution for that.
public static double CalculateTotalNightTimeHours(
DateTime arrival,
DateTime departure,
int nightTimeStartHour,
int nightTimeStartMinute,
int nightTimeEndHour,
int nightTimeEndMinute)
{
if (arrival >= departure)
return 0;
var nightStart = arrival.Date.AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
var nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);
double nightHours = 0;
while (departure > nightStart)
{
if (nightStart < arrival)
nightStart = arrival;
if (departure < nightEnd)
nightEnd = departure;
nightHours += (nightEnd - nightStart).TotalHours;
nightStart = nightStart.Date.AddDays(1).AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);
}
return nightHours;
}
You'd probably also want to add checking to make sure the start and end hours are within range. This also assumes that night starts on one day and ends on the next, so if you wanted night to end before midnight you'd have to do something else.

C# sorting values with respect to time

i wanted to create a program like this .
For every minute the time should be printed in the format of
h:m .For every 5 min it should print "break" this should continue for 24 hours ..
like this
0:0
0:1
0:2
0:3
0:4
break
0:6
0:7
0:8
0:9
break
0:11
.
.
.
23:59
i came with a program that solves it ..but i never used DateTime or any time function , i just used Thread.Sleep to dalay printing for 1 minute every time ...
i wanted to use some other method other than Thread.Sleep to solve it ...
so please guide me .. (sorry for my Bad english)
this is how i did with Thread.Sleep .
please provide me with any other solutions
using System;
using System.Threading;
class try22
{
public static void Main()
{
for(int i=0;i<24;i++)
{
for(int j=0;j<60;j++)
{
if(j%5 != 0 || (j == 0 && i == 0))
{
Thread.Sleep(20);
Console.WriteLine(i+":"+j);
}
else if(j%5 == 0 )
{
Thread.Sleep(20);
Console.WriteLine("break");
}
}
}
}
}
thanks guys i came up with the solution of using actual dates instead of array numbers in my problem
im getting weird errors with timer .. :( so i used thread.sleep itslef
using System;
using System.Threading;
class try22
{
public static void Main()
{
DateTime dt1 = new DateTime();
dt1 = DateTime.ParseExact("0:0", "H:m",null);
int cford=dt1.Day+1;
for (; dt1.Day!=cford; )
{
dt1 = addm(dt1);
Console.WriteLine(dts(dt1));
Thread.Sleep(60000);
}
}
public static string dts(DateTime dt)
{
string tmp = dt.ToString("H:m");
if (dt.Minute % 5 == 0)
return "BREAK";
else
return tmp;
}
public static DateTime addm(DateTime dt)
{
return dt.AddMinutes(1);
}
}
Which of these were you asked for?
Show the current time once per minute
Show the current time at the start of every minute like an alarm
Assuming 1, here's a couple of hints in the right direction (which should be helpful either way):
You can get the current date and time as a DateTime object using DateTime.Now
DateTime objects can return custom string output using .ToString("format").
Format is specified with a custom date and time format string. For example, to get the current hour in 24-hour time (without leading zeroes) you could use DateTime.Now.ToString("H").
As per the reference, you can include a string literal (unprocessed string) in your format. For example DateTime.Now.ToString("'Hour is: 'H") would return Hour is: 6
You can get the "minute" value of a DateTime object as an int using .Minute. For example, int minute = DateTime.Now.Minute;
If you want some code to run periodically, one way is to move it into its own method then setup a System.Threading.Timer like this:
void SomeMethod(object state) { /* DO STUFF HERE */ }
// Initialise the timer in your main() method
// As per MSDN for System.Threading.Timer, first number (0) is start delay.
// Second number (60000) is interval in milliseconds (60 seconds)
// This will cause SomeMethod to be called once every 60 seconds starting now.
Timer timer = new Timer(new TimerCallback(SomeMethod), null, 0, 60000);
You will need to stop your application exiting straight away after making the Timer (otherwise it will never get to run). One easy way to do this in a command line application is place a Console.Read() at the end of your Main() method which will wait for user input.
I have used Timer instead of Thread
class Program
{
private static System.Timers.Timer aTimer;
static int j = 0;
static int i = 0;
public static void Main()
{
// Create a timer with a Minute interval.
aTimer = new System.Timers.Timer(60000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 Minute (60000 milliseconds).
aTimer.Interval = 60000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.WriteLine(0 + ":" + 0);
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
j++;
if (j == 60)
{
Console.WriteLine("break");
j = 1;
i = i + 1;
}
if (i == 24)
{
i = 0;
}
if (j % 5 != 0 || (j == 0))
{
Console.WriteLine(i + ":" + j);
}
else if (j % 5 == 0)
{
Console.WriteLine("break");
}
}
}
I am not sure weather you want to use actual System time to start with or just the time since program execution started. Solution i am posting uses time since program started.
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
TimeSpan tt;
static void Main(string[] args)
{
Program p = new Program();
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(p.run));
t.Start();
while (true) ;
}
void run()
{
tt=new TimeSpan(0,1,0);
//Timer interval decides when even will be fired.
Timer t = new Timer(60000);
t.AutoReset = true;
t.Elapsed += new ElapsedEventHandler(t_Elapsed);
t.Start();
}
public void t_Elapsed(object sender, EventArgs e)
{
if (tt.Minutes % 5 == 0)
Console.WriteLine("Break");
Console.WriteLine(tt.Hours.ToString()+":"+tt.Minutes.ToString());
tt = tt.Add(new TimeSpan(0, 1, 0));
}
}
}

How do DateTime.ToBinary() and DateTime.ToFileTime() differ?

Can anyone help explain the difference between DateTime.ToBinary() and DateTime.ToFileTime()? As far as I can tell they seem to always return the same value (when dealing with UTC times at least). The same applies to DateTime.FromBinary() and DateTime.FromFileTime().
I've tried using Reflector and I can see some differences, I just don't understand the relevance of the magic numbers:
public long ToBinary()
{
if (this.Kind != DateTimeKind.Local)
{
return (long) this.dateData;
}
TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
long num2 = this.Ticks - utcOffset.Ticks;
if (num2 < 0L)
{
num2 = 0x4000000000000000L + num2;
}
return (num2 | -9223372036854775808L);
}
public long ToFileTime()
{
return this.ToUniversalTime().ToFileTimeUtc();
}
public long ToFileTimeUtc()
{
long num = ((this.InternalKind & 9223372036854775808L) != 0L) ? this.ToUniversalTime().InternalTicks : this.InternalTicks;
num -= 0x701ce1722770000L;
if (num < 0L)
{
throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid"));
}
return num;
}
public static DateTime FromFileTime(long fileTime)
{
return FromFileTimeUtc(fileTime).ToLocalTime();
}
public static DateTime FromFileTimeUtc(long fileTime)
{
if ((fileTime < 0L) || (fileTime > 0x24c85a5ed1c03fffL))
{
throw new ArgumentOutOfRangeException("fileTime", Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid"));
}
return new DateTime(fileTime + 0x701ce1722770000L, DateTimeKind.Utc);
}
public static DateTime FromBinary(long dateData)
{
long num2;
if ((dateData & -9223372036854775808L) == 0L)
{
return FromBinaryRaw(dateData);
}
long ticks = dateData & 0x3fffffffffffffffL;
if (ticks > 0x3fffff36d5964000L)
{
ticks -= 0x4000000000000000L;
}
bool isAmbiguousLocalDst = false;
if (ticks < 0L)
{
num2 = TimeZoneInfo.Local.GetUtcOffset(MinValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
}
else if (ticks > 0x2bca2875f4373fffL)
{
num2 = TimeZoneInfo.Local.GetUtcOffset(MaxValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
}
else
{
DateTime time = new DateTime(ticks, DateTimeKind.Utc);
bool isDaylightSavings = false;
num2 = TimeZoneInfo.GetUtcOffsetFromUtc(time, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
ticks += num2;
if (ticks < 0L)
{
ticks += 0xc92a69c000L;
}
if ((ticks < 0L) || (ticks > 0x2bca2875f4373fffL))
{
throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), "dateData");
}
return new DateTime(ticks, DateTimeKind.Local, isAmbiguousLocalDst);
}
ToBinary() and ToFileTimeUtc() do not return the same value. ToBinary provide a round-trip value, an Int64 that can preserve the properties of a DateTime. It uses the same time base, January 1st of the year 0. The value is always UTC. Bit 62 is set for the extreme corner case where a local time near the 1/1/00 would be negative when converted to UTC (paying attention to detail here :)). Bit 63 is set when the Kind is UTC. Convert the magic number to hex to see this.
ToFileTimeUtc() uses the same time base as Windows' FILETIME, January 1st of the year 1601. The magic number is the number of ticks for 12am, 1/1/1601.

Categories

Resources