How can I pack a Date and Time into 32-bits? - c#

I have a date represantation with the following order in order to fit an int. The date represantation should be
year : 6 bits
month : 5 bits
day : 5 bits
hours : 4 bits
minutes: 6 bits
seconds: 6 bits
All the dates should be fit into an Unit32 date
[year(5bits),month(5bits),day(6bits),hours(4bits),minutes(6bits),seconds(6bit)]
UInt32 date = 0;
date= date| (UInt32) (DateTime.Now.Year%2000)<< 26;
date= date| ((uint)DateTime.Now.Month << 22);
date= date| (uint)DateTime.Now.Day << 17;
date= date| ((uint)DateTime.Now.Hour << 15);
date= date| ((uint)DateTime.Now.Minute << 6);
date= date| ((uint)DateTime.Now.Second);
string binary = Convert.ToString(date, 2);
Above i have tried some bitwise operation but the result doestn satisfy. what i am missing or what should i do?
For Example current date is: 2021.55.10 13:55:06
Binary conversion above code 1010100110101101000110111000011 hex mean 54D6 8DC3 that means Thursday, 1 January 1970 06:01:58 but it should be today's date
thanks.

There's a few problems with your scheme:
year : 6 bits - 0 to 63
month : 5 bits - 0 to 31
day : 5 bits - 0 to 31
hours : 4 bits - 0 to 15
minutes: 6 bits - 0 to 63
seconds: 6 bits - 0 to 63
The main problem is that your scheme only uses 4 bits for hours - so it cannot represent times between 4pm and midnight (i.e. hours 16 through 23).
Secondarily, your scheme is inefficient because it wastes bits (there's 0-59 seconds in a minute, not 0-63).
...which means your scheme can represent invalid values, such as the 63rd second of the 63rd minute of the 15th hour of the 31st of February - which isn't a real date+time.
Rather than reinventing the wheel, why not use something like Unix time? (i.e. simply the number of seconds since an epoch).
Yes there is a reason memory reason which i cant use unix epox time
...so you need to fit the value into 32-bits. That's fine because you can use Unix time with 32-bit values. Of course this means you'll run into the Year 2038 problem but there's a few possible different solutions:
You can use a lower resolution.
e.g. 2-second or 1-minute resolution.
You can use a different epoch (base offset).
signed 32-bit Unix time uses 1970-01-01 00:00:00 with a max date+time value of 2038-01-19 03:14:07.
Unsigned 32-bit Unix time has a maximum of 2106-02-07 06:28:15.
If you use an epoch of 2000-01-01 00:00:00 with unsigned 32-bit integers then you have a max value of 2136-02-07 14:28:15.
This range of 135 full years is significantly better than your scheme because your scheme uses 6 bits for the year, which is 0-63, and last time I checked, 135 is greater than 63.
So here's a ready-made copy'n'pastable implementation of 32-bit Unix-time with an epoch of 2000-01-01 00:00:00:
private const Int64 YEAR_2000 = 946713600; // The year where there are no elephants. There is also no unethical treatment of elephants.
private static readonly DateTimeOffset _maxValueForUnsigned32Bits = DateTimeOffset( YEAR_2000 + UInt32.MaxValue ); // 2136-02-07 14:28:15
static UInt32 GetTimeAsUInt32( DateTimeOffset dt )
{
if (dt.Year < 2000 || dt > _maxValueForUnsigned32Bits ) throw new ArgumentOutOfRangeException( paramName: nameof(dt), actualValue: dt, message: "Must be between 2000 and 2136-02-07 14:28:15 inclusive." );
Int64 unixFrom2000_64 = dt.ToUnixTimeSeconds() - YEAR_2000;
// `unixFrom2000_64` *will always fit in 32-bits* due to the year range check above, and subtracting the new epoch.
UInt32 unixFrom2000_32 = (UInt32)unixFrom2000_64;
return unixFrom2000_32;
}
static DateTimeOffset GetTimeFromUInt32( UInt32 value )
{
Int64 asUnixTime = value + YEAR_2000;
return DateTimeOffset.FromUnixTimeSeconds( asUnixTime );
}
Usage:
DateTimeOffset now = DateTimeOffset.UtcNow; // WARNING: Using `Now` instead of `UtcNow` will include an offset value that will not be persisted.
Console.WriteLine( "Now: {0}", now );
UInt32 myTime = GetTimeAsUInt32( now );
Console.WriteLine( "As UInt32: {0:D}", myTime );
DateTimeOffset decoded = GetTimeFromUInt32( myTime );
Console.WriteLine( "Decoded from UInt32: {0}", decoded );
Gives me this output:
Now: 10/03/2021 11:26:43 +00:00
As UInt32: 668662003
Decoded from UInt32: 10/03/2021 11:26:43 +00:00

Related

Get Random Date with hours and minutes from now until 2 days ago

Hi How Can I get a random date with hours and minutes in a range bewtween now and 2 or 3 days ago. ??
Thanks to all
something like this dates time with minutes
10/23/2018 4:32:00 PM
10/23/2018 5:31:00 PM
10/23/2018 1:32:00 AM
10/22/2018 2:00:00 PM
Here I can get the dates in a range, let say 2 days, but the hour is the same
public static DateTime NextDateTime(int endDatenumbers)
{
DateTime startDate = DateTime.Today;
DateTime endDate = startDate.AddDays(-endDatenumbers);
var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks / int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours));
return newDate;
}
You should simplify that to 1 random call.
Get the furthest day which is 3 days ago.
var furthestDate= DateTime.Today.AddDays(-3);
You range is actually 2 days after that date which is (48hrs * 60 min) = 2880 minutes.
So anything from that date and 2880 minutes after is valid.
Simply get 1 random number between 0 an 2880. Finally simply add the minutes to the furthest date.
var randomDate = furthestDate.AddMinutes(YouRandomNumber);
The following logic actually computes the number of minutes between the two days. This is important where your days can potentially cross a daylight savings boundary. Also, I am storing the value "today" as technically (albeit unlikely) it could change between the two calls.
private static DateTime PickRandomMinute(int inPastNDays, Random random)
{
DateTime today = DateTime.Today;
int totalMinutes = (int)(today - today.AddDays(-inPastNDays)).TotalMinutes;
return today.AddDays(-inPastNDays).AddMinutes(random.Next(totalMinutes));
}
Example usage:
Random random = new Random();
Console.WriteLine(PickRandomMinute(2, random)); // 22/10/2018 9:34:00 PM (for example)
Console.WriteLine(PickRandomMinute(2, random)); // 23/10/2018 4:55:00 AM (for example)
You don't want to create a new Random within this method because calls that happen very close together would probably end up with the same seed and therefore return the same time.

How can I parse minutes to seconds?

I want to parse the following input "10:05" in format "minutes:seconds" in seconds. So 10:05 should be 10 * 60 = 600 + 5 = 605. How can I manage to do this with code ?
Just split the string, parse the numbers, and do your calculation:
string s = "10:05";
var parts = s.Split(':');
int seconds = int.Parse(parts[0]) * 60 + int.Parse(parts[1]);
Console.WriteLine(seconds); // 605
You can also use TimeSpan.Parse in this case which is able to parse this format if you add a hour part in front of it. You can then use the TotalSeconds property to get your desired result:
double seconds = TimeSpan.Parse("00:" + s).TotalSeconds;
Console.WriteLine(seconds); // 605
#poke is close, but you asked for seconds, thus:
string s= "10:05";
double seconds = TimeSpan.Parse("00:" + s).TotalSeconds;
Returns 605.
There are many ways to do this. Here are just a couple. If you know that the format is always going to be mm:ss then you could use the TimeSpan class, the ParseExact method, and the TotalSeconds property. Here's an example of how you could do it.
TimeSpan ts = TimeSpan.ParseExact(mytime, "mm:ss", System.Globalization.CultureInfo.InvariantCulture);
double seconds = ts.TotalSeconds;
If you have a bunch of different formats that can show up you can use the ParseExact and provide multiple time formats. Here's an example that takes a few formats.
//HH -> 24 hour format always with 2 digits ("08" = 8 hours)
// H -> 24 hour format with as few digits as possible ("8" = 8 hours)
//mm -> minutes always with 2 digits ("08" = 8 minutes)
// m -> minutes with as few digits as possible ("8" = 8 minutes)
//ss -> seconds always with 2 digits ("08" = 8 seconds)
// s -> seconds with as few digits as possible ("8" = 8 seconds)
string[] formats = new string["HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss", "ss", "s"];
TimeSpan ts = TimeSpan.ParseExact(mytime, formats, System.Globalization.CultureInfo.InvariantCulture);
double seconds = ts.TotalSeconds;
Here's a link to the MSDN documentation for the TimeSpan class. Check out the Methods and Properties for the TimeSpan class. Here's a link on formatting time strings.
The other way is to manually split the input string into the two parts and use the Convert class to convert each part into integers or doubles.
string[] timeparts = mytime.Split(':');
string minstr = timeparts[0];
string secstr = timeparts[1];
int mins = Convert.ToInt32(minstr);
int secs = Convert.ToInt32(secstr);
int seconds = mins * 60 + secs;
Here's the documentation for the Convert class.

hour interval based off of a 24 clock

I'm trying to figure an hour interval from a start time...
So if I allow the user to choose a value between 1 and 12 I want to figure out what times that represent in a 24 hour clock.
Lets say it is 9:00AM and they want to be notified every 4 hours during that day. I would need it to have the following values:
9AM
1PM
5PM
9PM
I'm trying to use the % (modulus) but I'm not getting what I'm expecting(4 % 24)... Any ideas?
Create a DateTime representing the current time (9:00 AM)
Create a TimeSpan representing the time interval (4 hours)
Use DateTime.Add(TimeSpan) method to produce the time of the next notification
The 12/24 hour clock does not play into it at all: you can format the next time the way you or your user wish - as a 24-hour clock using the "HH:mm" mask or as a 12-hour clock using "hh:mm" mask.
Here is a short code sample to get you started:
int hour = 9;
for (; hour <= 24; hour += 4)
Console.WriteLine("Hour = " + hour % 12);
Note the use of hour % 12.
Improvising... Use the % operator. As the % gets a value less than actual time (9:00AM) you know you need to change AM in PM... every time the result is less than actual time you have to change AM/PM or vice-versa.
int interval = 4;
int current = 9;
for(int i = current; i <= 24; i+=interval)
{
Console.WriteLine(i%12 + (i > 12 ? "PM" : "AM"));
}

LINQ to Entities DateTime is inconsistent

I have the following C# code that creates a DateTime, enters it into a table, and then queries that table:
DateTime date = DateTime.Now;
DateTest newRecord = new DateTest {
dateColumn = date
};
db.DateTest.AddObject(newRecord);
db.SaveChanges();
IQueryable<DateTest> records =
from d in db.DateTest
select d;
If I break the code at this point, and take a look at the objects in the debugger, I get this for the date object:
Date {11/22/2011 12:00:00 AM} System.DateTime
Day 22 int
DayOfWeek Tuesday System.DayOfWeek
DayOfYear 326 int
Hour 8 int
Kind Local System.DateTimeKind
Millisecond 345 int
Minute 59 int
Month 11 int
Second 33 int
Ticks 634575491733450602 long
TimeOfDay {08:59:33.3450602} System.TimeSpan
Year 2011 int
And I get this for the record retrieved from the table:
Date {11/22/2011 12:00:00 AM} System.DateTime
Day 22 int
DayOfWeek Tuesday System.DayOfWeek
DayOfYear 326 int
Hour 8 int
Kind Unspecified System.DateTimeKind
Millisecond 347 int
Minute 59 int
Month 11 int
Second 33 int
Ticks 634575491733470000 long
TimeOfDay {08:59:33.3470000} System.TimeSpan
Year 2011 int
As you can see, they're off by a couple milliseconds.
Can anyone explain why this is, and how I can fix it? I need to be able to query for records exactly matching a DateTime object in memory, but this behaviour is causing my queries to come up empty handed.
The resolution of the DateTime field in SQL Server is different from the one of the DateTime .NET class.
From MSDN - datetime (Transact-SQL):
Accuracy: Rounded to increments of .000, .003, or .007 seconds
So, in your case, the milliseconds get rounded up to the .007, giving .3470000 instead of .3450602.
The DateTime2 SQL Server datatype has a resolution of 100 nano seconds, like .NET, so may be a suitable replacement.
I think it is because you are using a DateTime column in the database. It does not have the same precision as the DateTime type in .NET. Try using column type DateTime2 in the database instead.

Get trimester (quarter) code in c#

i needed to get the correspondent trimester (periods of 3 months, being the first trimester Jan, Feb and Mar) of a given date. Using the c# System.DateTime struct I didn't manage to find a method for what I was looking for. So I solved like this:
DateTime sDeathDate = DateTime.Parse("18/09/1970");
int iDeathTrimester = Convert.ToInt32(Math.Round(Convert.ToDouble(sDeathDate.Month) / 3 + 0.25));
If someone knows a easier way to do this, please answer.
André
Assuming Jan - Mar is trimester 1, Apr - Jun is trimester 2, Jul - Sep is Trimester 3 and Oct - Dec is trimester 4, then you can use
int trimester = (sDeathDate.Month - 1) / 3 + 1
This is the same as a quarter, did you mean something different?
Math.Ceiling Returns the smallest integer greater than or equal to the specified number.
DateTime sDeathDate = DateTime.Parse("18/11/1970");
int trimester = (int)Math.Ceiling(sDeathDate.Month/3.0);
Note that the code use 3.0 to perform a floating point division and not an integer division
The Time Period Library for .NET includes the class Quarter (period of 3 months):
// ----------------------------------------------------------------------
public void QuarterOfDateSample()
{
DateTime moment = new DateTime( 1970, 9, 15 );
Console.WriteLine( "Quarter : {0}", new Quarter( moment ) );
// > Quarter : Q3 1970; 01.07.1970- 30.09.1970| 91.23:59
Console.WriteLine( "Quarter : {0}", new Quarter( 2006, YearQuarter.First ) );
// > Quarter : Q1 2006; 01.01.2006 - 31.03.2006 | 89.23:59
} // QuarterOfDateSample
If you use Math.Round (Double, MidpointRounding) you can do the round better without adding 0,25
See you

Categories

Resources