I'm trying to create list of hours my code like
var hours = Enumerable.Range(00, 24).Select(i => i.ToString("D2")));
it generates something like this in 24 hour format
but actually i need same thing not on 24 hours but 12 like after with AM PM postfix
what is the best way to generate hour list with 00.00 AM/PM formatted
Thanks
You can create a DateTime instance then use ToString format of hh.mm tt.
var hours = Enumerable.Range(00, 24)
.Select(i => new DateTime(2000,1,1,i,0,0).ToString("hh.mm tt"));
You need to execute the query using something like ToArray() to get the result since the behavior of linq is deferred execution.
var hours = Enumerable.Range(00, 24).Select(i => (DateTime.MinValue.AddHours(i)).ToString("hh.mm tt"));
You're dealing with time, so using appropriate type, DateTime, seems better than using int:
var hours = from i in Enumerable.Range(0, 24)
let h = new DateTime(2014, 1, 1, i, 0, 0)
select h.ToString("t", CultureInfo.InvariantCulture);
var startDate = DateTime.Today;
IEnumerable<DateTime> listOfHours = Enumerable.Range(0, 24).Select(h => startDate.AddHours(h));
If you need more flexibility and have from/to for specific times that overlap midnight (and increase step to let's say every 2h) you can use something like this:
private static IEnumerable<string> GetListOfHours(DateTime start, DateTime end, int step)
{
while (start <= end)
{
yield return start.ToString("hh.mm tt");
start = start.AddHours(step);
}
}
So this:
var start = DateTime.Now.Date.AddHours(6); // 6 am
var end = DateTime.Now.AddDays(1).Date.AddHours(2); // 2 am
var step = 1;
var list = GetListOfHours(start, end, step);
Will produce this:
06.00 AM
07.00 AM
08.00 AM
09.00 AM
10.00 AM
11.00 AM
12.00 PM
01.00 PM
02.00 PM
03.00 PM
04.00 PM
05.00 PM
06.00 PM
07.00 PM
08.00 PM
09.00 PM
10.00 PM
11.00 PM
12.00 AM
01.00 AM
02.00 AM
https://dotnetfiddle.net/8LYxA6
Related
How can I convert the following into times, knowing that the values are the number of minutes.
350-659, 1640-2119, 2880-3479;
The output id like is
M 5:50am - 10:59am
T 3:20am - 10:59am
W 12:00am - 9:59am
etc....
Ranges -
Mon= 0-1439
Tue = 1440-2879
Wed = 2880 - 4319
Thurs = 4321 - 5759
Fri = 5760 - 7199
Sat = 7200 - 8639
Sun = 8640 - 10079
What I have so far is
var days = new[] { 24, 48, 72, 96, 120, 144, 168 };
var numbers = Enumerable.Range(1,7);
var hours = days.ToDictionary(x => (double)x/24, i => (int)I*60);
which outputs
Key Value
1 1440
2 2880
3 4320
4 5760
5 7200
6 8640
7 10080
I kinda don't get the question at all, but taking everything you've said at face value:
var times = "350-659, 1640-2119, 2880-3479;"
.Split(',') //split to string pairs like "350-659"
.Select(s => s.Split('-').Select(x => int.Parse(x)).ToArray()) //split stringpairs to two strings like "350" and "659", then parse to ints and store as an array
.Select(sa => new { //turn array ints into dates
F = new DateTime(0).AddMinutes(sa[0]), //date 0 i.e. jan 1 0001 was a monday. add minutes to it to get a time and day
T = new DateTime(0).AddMinutes(sa[1] + 1) //add 1 to the end minute otherwise 659 is 10:59pm and you want 11:00am
}
)
.Select(t =>
$"{($"{t.F:ddd}"[0])} {t.F:hh':'mmtt} - {t.T:hh':'mmtt}" //format the date to a day name and pull the first character, plus format the dates to hh:mmtt format (eg 09:00AM)
);
Console.Write(string.Join("\r\n", times));
If you actually want to work with these things in a sensible way I recommend you stop sooner than the final Select, which stringifies them, and work with the anonymous type t that contains a pair of datetimes
The only thing about this output that doesn't match the spec, is that the AM/PM are uppercase. If that bothers you, consider:
$"{t.F:ddd}"[0] + ($" {t.F:hh':'mmtt} - {t.T:hh':'mmtt}").ToLower()
You could get the current monday of the week and add the minutes. I don't think you can do this in Linq directly.
//your timestamp
int minutes = 2345;
//get the day of week (sunday = 0)
int weekday = (int)DateTime.Now.DayOfWeek - 1;
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
weekday = 6;
//get the first day of this week
DateTime firstDayOfWeek = DateTime.Now.AddDays(-1 * weekday);
//add the number of minutes
DateTime date = firstDayOfWeek.Date.AddMinutes(minutes);
An interval of time (as opposed to an absolute point in time) is expressed as a TimeSpan. In this case, you'd have one TimeSpan that represents the offset (from the beginning of the week) until the starting time, then another TimeSpan that represents the offset to the end time.
Here's how to convert your string into a series of TimeSpans.
var input = #"540-1019;1980-2459;3420-3899;4860-5339;6300-6779";
var times = input
.Split(';')
.Select(item => item.Split('-'))
.Select(pair => new
{
StartTime = new TimeSpan(hours: 0, minutes: int.Parse(pair[0]), seconds: 0),
EndTime = new TimeSpan(hours: 0, minutes: int.Parse(pair[1]), seconds: 0)
})
.ToList();
foreach (var time in times)
{
Console.WriteLine
(
#"Day: {0} Start: {1:h\:mm} End: {2:h\:mm}",
time.StartTime.Days,
time.StartTime,
time.EndTime
);
}
Output:
Day: 0 Start: 9:00 End: 16:59
Day: 1 Start: 9:00 End: 16:59
Day: 2 Start: 9:00 End: 16:59
Day: 3 Start: 9:00 End: 16:59
Day: 4 Start: 9:00 End: 16:59
You can of course choose to format the TimeSpan in any way you want using the appropriate format string.
I encountered issue comparing DateTime values from CRM and Excel.
1. DateTime excelDT1 = Convert.ToDateTime(row[Excel.notificationdate].ToString().Trim(), System.Globalization.CultureInfo.GetCultureInfo("hi-IN").DateTimeFormat); ;
2. var excelDT2 = row[Excel.notificationdate].ToString().Trim();
3. var excelDT3 = row[Excel.notificationdate];
4. DateTime crmDT1 = Convert.ToDateTime(caseEntity.Attributes[Case.notificationdate].ToString().Trim(), System.Globalization.CultureInfo.GetCultureInfo("hi-IN").DateTimeFormat); ;
5. var crmDT2 = caseEntity.Attributes[Case.notificationdate].ToString().Trim();
6. var crmDT3 = caseEntity.Attributes[Case.notificationdate];
Below are the outputs respectively:
excelDT1: 1/13/2020 12:00:00 AM
excelDT2: 13/01/2020
excelDT3: 13/01/2020
crmDT1: 12/1/2020 4:00:00 PM
crmDT2: 1/12/2020 4:00:00 PM
crmDT3: 1/12/2020 4:00:00 PM
May I know how can I format the above such that they can be checked if they are equal?
Thank you.
You can compare 1st and 4th with public static bool Equals (DateTime t1, DateTime t2);
var result = DateTime.Equals(excelDT1, crmDT1);
I have a list of dates as strings in the format 'dd/mm/yyyy hh:mm:ss tt' I'm trying to order them by closest to farthest like so:
09/12/2018 12:00:00 PM
10/12/2018 12:00:00 PM
11/12/2018 12:00:00 PM
My code seems to be ordering them from the 11th to the 09th which I don't want but can't seem to get right.
DateTime now = DateTime.Now;
var ordered = herds.HerdList.OrderBy(n => (now - DateTime.Parse(n.Date_Visit)).Duration());
The above code gives me:
11/12/2018 12:00:00 PM
10/12/2018 12:00:00 PM
09/12/2018 12:00:00 PM
How can I order it the other way around?
Thanks
How can I order it the other way around?
Use OrderByDescending instead of OrderBy
You can flip the order of any Orderby(x => whatever) by simply using OrderByDescending(x => whatever).
var ordered = herds.HerdList.OrderBy(n => DateTime.Parse(n.Date_Visit));
I am building something like exam datesheet. I'm currently having issues in finding conflicts between time..
I have a List of strings that stores time intervals like-
List<string> times = new List<string>();
times.Add("6:00 PM to 9:00 PM");
times.Add("10:00 AM to 1:00 PM");
Now suppose, if want to add below time to the list, I first want to check it does not conflict with the time that is already there.
So, in below case, it should not be added.
if(NotConflict("5:00 PM to 7:00 PM"))
times.Add("5:00 PM to 7:00 PM");
But the following can be added since there is no conflict.
if(NotConflict("2:00 PM to 5:00 PM"))
times.Add("2:00 PM to 5:00 PM");
I cannot use DateTime here because it the very old system and time is being stored like above. And it being used at many places.
This should work:
private static Tuple<DateTime, DateTime> ParseDate(string dateTimes)
{
var split = dateTimes.Split(new[] { " to " }, StringSplitOptions.None);
var time1 = DateTime.ParseExact(split[0], "h:mm tt",
CultureInfo.InvariantCulture);
var time2 = DateTime.ParseExact(split[1], "h:mm tt",
CultureInfo.InvariantCulture);
return Tuple.Create(time1, time2);
}
private static bool NotConflict(IEnumerable<string> times, string time) {
var incTime = ParseDate(time);
return !times.Any(t => {
var parsed = ParseDate(t);
return incTime.Item1 <= parsed.Item2 && parsed.Item1 <= incTime.Item2;
});
}
public static void Main()
{
var times = new List<string>();
times.Add("6:00 PM to 9:00 PM");
times.Add("10:00 AM to 1:00 PM");
Console.WriteLine("No Conflict 5:00 PM to 7:00 PM: {0}", NotConflict(times, "5:00 PM to 7:00 PM"));
Console.WriteLine("No Conflict 2:00 PM to 5:00 PM: {0}", NotConflict(times, "2:00 PM to 5:00 PM"));
}
ParseDate will return a formatted tuple with the start and end time in Item1 and Item2 respectively. Then you simply use Linq's Any function to filter and make sure that you don't return any that fall within the bounds.
See the DotNet fiddle here.
I have a time range 11:00 PM to 5:00 AM. (night hours range)
I have date range for eg.,
2014-04-01 00:00:00 to 2014-04-02 23:59:59
Now I need to calculate how many night hours are present in the given date range.
For the above example it should return 11 hours 59 minutes 59 seconds
Explanation:
2014-04-01 00:00 AM to 2014-04-01 5:00 AM = 5 hours
2014-04-01 11:00 PM to 2014-04-02 5:00 AM = 6 hours
2014-04-02 11:00 PM to 2014-04-02 11:59:59 PM = 0 hour 59 minutes 59 seconds
one second approximation is okay.
If these are strings, you need to parse them to DateTime with DateTime.ParseExact method and then get difference them with - operator. This gets you a TimeSpan. I see your strings have different formats. You need to parse them matched format one by one.
After that, you can use TimeSpan properties like;
string s = "2014-04-01 00:00 AM";
var date = DateTime.ParseExact(s,
"yyyy-MM-dd HH:mm tt",
CultureInfo.InvariantCulture);
string s1 = "2014-04-01 5:00 AM";
var date1 = DateTime.ParseExact(s1,
"yyyy-MM-dd H:mm tt",
CultureInfo.InvariantCulture);
TimeSpan ts = date1 - date;
Console.WriteLine(string.Format(#"{0} hours {1} minutes {2} seconds",
ts.Hours, ts.Minutes, ts.Seconds));
Output will be;
5 hours 0 minutes 0 seconds
If they are already DateTime, just use - operator and use .Hours, .Minutes and .Seconds properties of TimeSpan structure.
There is a project called Calculating Business Hours which is calculate business hours between two DateTime. You can implement your own night shift hours based this project.
You can use the CalendarPeriodCollector of the Time Period Library for .NET:
// ----------------------------------------------------------------------
public void NightHours()
{
CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter();
filter.CollectingHours.Add( new HourRange( 0, 5 ) ); // working hours
filter.CollectingHours.Add( new HourRange( 23, 24 ) ); // working hours
CalendarTimeRange testPeriod =
new CalendarTimeRange( new DateTime( 2014, 4, 1 ),
new DateTime( 2014, 4, 3 ) );
Console.WriteLine( "Calendar period collector of period: " + testPeriod );
CalendarPeriodCollector collector =
new CalendarPeriodCollector( filter, testPeriod );
collector.CollectHours();
Console.WriteLine( "Duration: " + new DateDiff( collector.Periods.TotalDuration ) );
} // NightHours