show timespan values after changed into local time - c#

Our db server is outside of the country.. So i stored the created date using TimeZoneInfo like following,
DateTime dateTime = DateTime.Now;
var timeZone = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dateTime, TimeZoneInfo.Local.Id, "India Standard Time");
In page, i am showing used by Timespan. I create separate class for that..
My code
public static string GetFriendlyDate(DateTime dateTime)
{
TimeSpan ts = DateTime.Now.Subtract(dateTime);
string friendlyDate = dateTime.ToShortDateString();
int totalDays = (int)System.Math.Round(ts.TotalDays);
int totalHours = (int)System.Math.Round(ts.TotalHours);
int totalMinutes = (int)System.Math.Round(ts.TotalMinutes);
int totalSeconds = (int)System.Math.Round(ts.TotalSeconds);
int totalMilliSeconds = (int)System.Math.Round(ts.TotalMilliseconds);
int totalMonths = totalDays / 31; //approx.. change this
int totalYears = totalDays / 365; //approx.. change this
if (totalYears > 0) //give in terms of years
{
if (totalYears == 1)
friendlyDate = "last year";
else
friendlyDate = totalYears + " years ago";
}
else if (totalMonths > 1) //give in terms of months
{
if (totalMonths == 1)
friendlyDate = "last month";
else
friendlyDate = totalMonths + " months ago";
}
else if (totalDays > 1) //give in terms of days (at least 2 days)
{
friendlyDate = totalDays + " days ago";
}
else if (totalHours > 0) //give in terms of hours
{
if (totalHours == 1)
friendlyDate = "1 hour ago";
else
friendlyDate = totalHours + " hours ago";
}
else if (totalMinutes > 0) // give in terms of minutes
{
if (totalMinutes == 1)
friendlyDate = "1 minute ago";
else
friendlyDate = totalMinutes + " minutes ago";
}
else if (totalSeconds > 0) //give in terms of seconds
{
if (totalSeconds == 1)
friendlyDate = "1 second ago";
else
friendlyDate = totalSeconds + " seconds ago";
}
else //just now
{
friendlyDate = "a moment ago";
}
return friendlyDate;
}
when i run local it shows correctly "--seconds ago"... like that.. But in server it is always showing a moment ago, after some hours it is taking "---hours ago" like that..
can anyone please help me out of this problem?

If i want to get a correct way what i asked my question, i have to convert the time into UTC.
so i changed that..
var utcTime = DateTime.UtcNow.AddHours(5).AddMinutes(30);
TimeSpan ts = utcTime.Subtract(dateTime);
Now the issues is solved...

You were storing items as of India Standard Time, and then comparing them against the local time.
The solution you gave in your answer is adjusting the time back to India Standard Time, which is fixed at +5:30 offset from UTC. This only works because IST does not have any daylight saving time rules. If you were using a different time zone, such as US Eastern Time, it would not work reliably.
The correct solution is to store the original value as UTC. Instead of using DateTime.Now and converting to IST, just use DateTime.UtcNow and store the value directly. When you compare in your GetFriendlyDate method, you should also use DateTime.UtcNow as the basis for comparison.
If you already have data saved in your database in India Standard Time, then you will need to update those values when you make this change. For example, if this is SQL Server, you could run the following script to update your values from IST to UTC:
UPDATE mytable SET thedatetime = DATEADD(minute, -330, thedatetime)
In general, local date/time values such as those retrieved from DateTime.Now have no business being in a web application. Read The Case Against DateTime.Now.

Related

How to remove seconds from TimeSpan? [duplicate]

This question already has answers here:
Convert TimeSpan from format "hh:mm:ss" to "hh:mm"
(7 answers)
Closed 4 years ago.
Beginner in xamarin. Im tring to display the time as HH:mm without the seconds being added in. It appears on my form as example 12:30:00, i want just as 12:30. Do i need to change Date time function maybe, the code is currently working but displaying the time as hour minute seconds still.
The code also should allow the soonest time to appear at the top but it doesnt seem to be doing that either.
void FindNextDue(ObservableCollection<UserMedDosagePayLoad> medtimes)
{
UserMedTimesFilteredList.Clear();
int nowHour = DateTime.Now.Hour;
int nowMinutes = DateTime.Now.Minute;
TimeSpan now = new TimeSpan(nowHour, nowMinutes, 0);
foreach (UserMedDosagePayLoad item in medtimes)
{
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time;
string[] DT = item.Time.Split(':');
if (DT[0] != null)
{
int hr = Convert.ToInt32(DT[0]);
int minutes = Convert.ToInt32(DT[1]);
TimeSpan medTime = new TimeSpan(hr, minutes, 0);
TimeSpan comparison = now.Subtract(medTime).Negate();
TimeSpan TwentyFourHour = new TimeSpan(24, 0, 0);
if (comparison.TotalMilliseconds <0)
{
comparison = TwentyFourHour.Add(comparison);
}
TimeComparison.Add(comparison);
}
}
//Order the collection of times so the next due is always first
TimeComparison = new List<TimeSpan>(TimeComparison.OrderBy(h => h.Hours)
.ThenBy(m => m.Minutes));
List<string> UserMedIDs = new List<string>();
for (int i = 0; i < TimeComparison.Count(); i++)
{
DateTime NextDue = DateTime.Now.Add(TimeComparison[i]);
DateTime NextDueToCompare = new DateTime(NextDue.Year, NextDue.Month,
NextDue.Day, NextDue.Hour, NextDue.Minute, 0);
string NextDueComparisonString = NextDueToCompare.ToString("HH:mm:ss");
foreach (UserMedDosagePayLoad item in UserMedTimes)
{
if (item.Time == NextDueComparisonString &&
!UserMedIDs.Contains(item.Usermedid))
{
UserMedTimesFilteredList.Add(item);
UserMedIDs.Add(item.Usermedid);
}
}
UserMedTimes = medtimes;
MedicationList.ItemsSource = UserMedTimesFilteredList;
BusyIndicator.IsRunning = false;
}
}
If you only want hours and minutes to display, then remove "ss" from your format string
string NextDueComparisonString = NextDueToCompare.ToString("HH:mm:ss");
here, you are not specifying any format so it is using the default
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time;
specify a format like this
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time.ToString("HH:mm");
Use formatting if you don't want to see the seconds at all (12:48 for example).
The method gets a TimeSpan obj, and returns the time as a string without the seconds.
Read here to explore more about formatting.
The custom function
public string GetTimeSpanWithoutSeconds(TimeSpan input)
{
return input.ToString(#"hh\:mm");
}
The "hh" custom format specifier
Represents the hour as a number from 01 through 12; that is, the hour is represented by a 12-hour clock that counts the whole hours since midnight or noon. A particular hour after midnight is indistinguishable from the same hour after noon. The hour is not rounded, and a single-digit hour is formatted with a leading zero. For example, given a time of 5:43 in the morning or afternoon, this format specifier displays "05".
The "mm" custom format specifier
Represents the minute as a number from 00 through 59. The minute represents whole minutes that have passed since the last hour. A single-digit minute is formatted with a leading zero.

Convert DateTime (TimePart) to a readable days, hours and minutes based on a day hour

I have a code in c# and I need to accumulate all the hours in a DateTime format.
I have a foreach statement where I calculate pending hours but that pending hours need to be accumulated so at the end I have a total of hours and minutes and based on a day limit hours for example my day could be a 8 hours day, then I can format it as string like the following example:
If my total hours is: 24 hours 31 minutes then based on a 8 hour day I should format as follows:
3 days, 31 minutes.
I need to know the best way to accumulate the hours, here is the code that is inside my foreach:
// here I create a Timespan in order to get hours and minutes from a DB.
var timeSpan = TimeSpan.FromHours(double.Parse(drItem["PayableHours"].ToString()));
int hh = timeSpan.Hours;
int mm = timeSpan.Minutes;
int ss = timeSpan.Seconds;
// pending hours
// here i create a tempHours variable for a 8 hour
DateTime tempHours = new DateTime(1900, 1, 1, 8, 0, 0);
// here I substract from my 8 hour datetime the hours and the minutes of my timespan
DateTime pendingHours = dayHours.Add(new TimeSpan(-hh,-mm,0));
// here i should accumulate the pendingHours so when the foreach statement finish I can format the total hours and minutes to string.
Any clue?
From what I understand, it would look something like this:
private static string PrettyPrint(TimeSpan timeSpan)
{
var parts = new List<string>();
int totalHours = (int)timeSpan.TotalHours;
int workDays = totalHours / 8;
int remainingHours = (int)timeSpan.TotalHours - 8 * workDays;
if (workDays == 1) parts.Add("1 day");
if (workDays > 1) parts.Add(workDays + " days");
if (remainingHours == 1) parts.Add("1 hour");
if (remainingHours > 1) parts.Add(timeSpan.Hours + " hours");
if (timeSpan.Minutes == 1) parts.Add("1 minute");
if (timeSpan.Minutes > 1) parts.Add(timeSpan.Minutes + " minutes");
return string.Join(", ", parts);
}
You might want to also add some code to check for TimeSpan.Zero.
If I understand your question correctly, then:
int numberDays = hh / 8;
will give you the number of days. From there, the rest should be easy.

how can i get the interval in hrs AM to PM and PM to AM

i need help guys im creating an Overtime computation and when im trying to get the value of the value hrs it became negative when i subtract the PM to AM and PM to PM coz i need to count the hrs when it reach at 10:00 PM heres my code
string value = comboBox91.Text;
string value2 = comboBox92.Text;
string awtsu = value;
DateTime dt;
DateTime dt2;
dt = DateTime.Parse(value);
string mystring;
mystring = dt.ToString("hh:mm tt");
dt2 = DateTime.Parse(value2);
string mystring2;
mystring2 = dt2.ToString("hh:mm tt");
double diff2 = (dt2 - dt).TotalHours;
textBox8.Text = Convert.ToString(diff2) + "Hrs";
string pmm = "10:00 PM";
DateTime pm = DateTime.Parse(pmm);
string mystring3;
mystring3 = pm.ToString("hh:mm tt");
if (dt2 > pm)
{
double diff = (dt - dt2).TotalHours;
textBox9.Text = Convert.ToString(diff) + "Hrs";
}
else
{
textBox9.Text = ("0");
}
$
Let me see if I understand your requirements:
A worker starts at a standard time (8:30 AM) and usually finish at a standard time (6:30 PM), but may work later. In theory that person might work past midnight into the next day.
If they work past 7 PM up to 10 PM they get paid one overtime rate.
If they work past 10 those hours are paid a second rate.
So, the first thing you would declare in your code is a list of these overtime boundaries:
public static readonly TimeSpan[] OvertimeBoundaries =
{
TimeSpan.FromHours(19), // 7 PM
TimeSpan.FromHours(22) // 10 PM.
};
TimeSpan is a structure that represents an interval of time and is appropriate to represent a daily event.
Next, given a workers start and end times, you want to measure the total number of hours for each of these intervals:
public static TimeSpan[] GetOvertimeWorked(DateTime startDateTime, DateTime endDateTime, IList<TimeSpan> overtimeBoundaries)
{
var overtimeWorked = new TimeSpan[overtimeBoundaries.Count];
for (int i = 0; i < overtimeBoundaries.Count - 1; i++)
{
var time1 = startDateTime.Date + overtimeBoundaries[i];
var time2 = startDateTime.Date + overtimeBoundaries[i + 1];
if (time1 > time2)
throw new ArgumentException("overtimeBoundaries are not in order");
if (endDateTime > time2)
overtimeWorked[i] = time2 - time1;
else if (endDateTime > time1)
overtimeWorked[i] = endDateTime - time1;
else
overtimeWorked[i] = TimeSpan.Zero;
}
if (overtimeWorked.Length > 0)
{
var timeLast = startDateTime.Date + overtimeBoundaries[overtimeBoundaries.Count - 1];
if (endDateTime > timeLast)
overtimeWorked[overtimeBoundaries.Count - 1] = endDateTime - timeLast;
else
overtimeWorked[overtimeBoundaries.Count - 1] = TimeSpan.Zero;
}
return overtimeWorked;
}
Finally you need to extract the appropriate date & time information from your user interface, call the above utility to get overtime hours worked, and display it.
Your code would be much more comprehensible if you named your variables meaningfully rather than with names like "dt2" and "awtsu". You should also, at the minimum, separate your business logic from the code that loads and unloads data from the user interface.
Finally, I will note that the following is dangerous:
string pmm = "10:00 PM";
DateTime pm = DateTime.Parse(pmm);
The problem here is that, if you pass "DateTime.Parse" a string with only a "time of day" component, it will fill in the date information with the current clock setting on your computer. This would likely produce random, hard to reproduce bugs if you put your application into production, because the app might or might not be run on a different day than the workers worked!

Rounding up a time to the nearest hour

ok basically I have a program that is re-writing text files and formatting them through various conditions, one of the conditions is that the date and time values in my original text file needs to be removed from its current location and moved into a new column I have created, this is done with the code below. I used a regex to find the date and time format and then remove it from its current location and store the value in a variable that I can use later...
if (line.Contains(date))
{
string pattern = #"(\d{2}:\d{2}:\d{2}\s?\d{2}/\d{2}/\d{4})";
string input = line;
string replacement = "";
Regex rgx = new Regex(pattern);
date1 = rgx.Match(input).ToString();
string result = rgx.Replace(input, replacement);
line = result;
}
This new value that is returned gets both the time and date values but only as one string, so I then used a split (shown below) to get the two values separate, now split[0] is my time variable (00/00/00 format) - which I now need to round up to the nearest hour. I am really not sure how to go about this, any ideas ?
string[] split = date1.Split(' ');
writer.WriteLine(split[0] + "\t" + split[1] + "\t" + line);
Get that date from the string into a DateTime struct. See for example the TryParseExact method
Then you can create a new DateTime value, based on year/month/day/hour of the value from the previous step, setting the minute and second parts to zero (see here )
Add one hour if the minutes or seconds part (of your first value) is not zero, using .AddHours(1), which returns a new DateTime value.
EDIT
Some sample code:
string inputdate = "2:56:30 8/7/2014";
DateTime dt;
System.Globalization.CultureInfo enUS = new System.Globalization.CultureInfo("en-US");
if (DateTime.TryParseExact(inputdate, "H:m:s d/M/yyyy", // hours:minutes:seconds day/month/year
enUS, System.Globalization.DateTimeStyles.None, out dt))
{
// 'dt' contains the parsed date: "8-7-2014 02:56:30"
DateTime rounded = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0);
if (dt.Minute > 0 || dt.Second > 0) // or just check dt.Minute >= 30 for regular rounding
rounded = rounded.AddHours(1);
// 'rounded' now contains the date rounded up: "8-7-2014 03:00:00"
}
else
{
// not a correct date
}
In my case, I need to round it to lower hour, and I used this logic:
DateTime x = new DateTime();
x = x.Date.AddHours(x.Hour);
You can try one liner solution to convert your DateTime to nearest hour,
//Input DateTime
DateTime input = DateTime.ParseExact("28/05/2021 2:16 PM", "dd/MM/yyyy h:mm tt", CultureInfo.InvariantCulture);
//Ternary Operation
var output = input.Minute > 30 //Check if mins are greater than 30
? input.AddHours(1).AddMinutes(-input.Minute) //if yes, then add one hour and set mins to zero
: input.AddMinutes(-input.Minute); //otherwise set mins to zero
Console.WriteLine(result.ToString());
Try Online: .NET Fiddle
Can you convert the string to a datetime?
Something like:
dateVariable = Convert.ToDateTime(dateString);
int hour = dateVariable.Hour;
int minute = dateVariable.Minute;
And then do the rounding.
Now as you have
string[] str = split[1].Split('/');
// create a new DateTime
int minutes = int.Parse(str[1]);
if(minutes >= 30)
hour = int.Parse(str[0]) + 1 // make sure if it 13 or 25 make it 1
minutes = 0 ;
sec = 0;
else {
hour = int.Parse(str[0]);
minutes = 0 ;
sec = 0 ;
}
var myDate = new Date(Year, month , day , hour , minutes , sec);
In C#
var Now = DateTime.Now;
var Nearest = Now.Date;
Nearest = Nearest.AddHours(Now.Hour + (Now.Minute >= 30 ? 1 : 0));
Now = Current time
Nearest = Rounded to the nearest hour

Calculate time different between PM and AM in c# windows phone 7

I am trying to calculate time difference in PM and AM.
I have data of Monday 1:01 PM and tuesday 1:00AM.
I used below code to calculate the time difference.
And the result i get is:
-12 hour and -1 minutes
How should i go about doing it getting the correct time difference?
Below is the code:
if ((dayNow == "Monday") && (tues == "True"))
{
DateTime timeNow = DateTime.ParseExact(DateTime.Now.ToShortTimeString(),
"h:mm tt", new DateTimeFormatInfo());
DateTime timeSelected = DateTime.ParseExact(timePicker.ValueString,
"h:mm tt", new DateTimeFormatInfo());
TimeSpan timeLeft = timeSelected.Subtract(timeNow);
if (timeSelected > timeNow)
{
string hour = timeLeft.Hours.ToString();
string minute = timeLeft.Minutes.ToString();
string timeDifference = "This alarm is set for " + "1 day and "
+ hour + " hour and " + minute + " minutes from now.";
MessageBox.Show(timeDifference, "Alarm", MessageBoxButton.OK);
NavigationService.Navigate(new Uri("/listOfAlarm.xaml?",
UriKind.Relative));
}
else if (timeSelected < timeNow)
{
string hour = timeLeft.Hours.ToString();
string minute = timeLeft.Minutes.ToString();
string timeDifference = "This alarm is set for " + hour +
" hour and " + minute + " minutes from now.";
MessageBox.Show(timeDifference, "Alarm", MessageBoxButton.OK);
NavigationService.Navigate(new Uri("/listOfAlarm.xaml?",
UriKind.Relative));
}
else
{
NavigationService.Navigate(new Uri("/listOfAlarm.xaml?",
UriKind.Relative));
}
}
Bit Late to the show, but here is what I did.
An If statement, that figures out whether the time you have selected is greater than, or less than. If it is less than, then it will automatically add 24 hours to compensate, thus removing the negative sign and compensating for the program.
I converted the times to Integers, and then did this:
if (timeSelected > timeNow)
{
int_hour = Convert.ToInt16(hour); // Convert the string to integer
}
else
{
int_hour = Convert.ToInt16(hour) + 24; // Convert the string to integer ( Compensates for Negative)
}
Does replacing:
TimeSpan timeLeft = timeSelected.Subtract(timeNow);
with
TimeSpan timeLeft = timeNow.Substract(timeSelected);
fix your problem?

Categories

Resources