Regular expression to validate valid time - c#

I need a regular expression to validate time.
Valid values would be from 0:00 to 23:59.
When the time is less than 10:00 it should also support one character numbers.
These are valid values:
9:00
09:00

Try this regular expression:
^(?:[01]?[0-9]|2[0-3]):[0-5][0-9]$
Or to be more distinct:
^(?:0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$

I don't want to steal anyone's hard work but this is exactly what you're looking for, apparently.
using System.Text.RegularExpressions;
public bool IsValidTime(string thetime)
{
Regex checktime =
new Regex(#"^(20|21|22|23|[01]d|d)(([:][0-5]d){1,2})$");
return checktime.IsMatch(thetime);
}

I'd just use DateTime.TryParse().
DateTime time;
string timeStr = "23:00"
if(DateTime.TryParse(timeStr, out time))
{
/* use time or timeStr for your bidding */
}

The regex ^(2[0-3]|[01]d)([:][0-5]d)$ should match 00:00 to 23:59. Don't know C# and hence can't give you the relevant code.
/RS

If you want to allow military and standard with the use of AM and PM (optional and insensitive), then you may want to give this a try.
^(?:(?:0?[1-9]|1[0-2]):[0-5][0-9]\s?(?:[AP][Mm]?|[ap][m]?)?|(?:00?|1[3-9]|2[0-3]):[0-5][0-9])$

Very late to the party but I created this Regex which I found work the best for 24H format (HH:mm:ss OR HH:mm OR H:mm:ss OR H:mm):
private bool TimePatternValidation(string time)
=> new Regex(#"^(([0-1]?[0-9])|([2][0-3]))(:([0-5][0-9])){1,2}$").IsMatch(time);

[RegularExpression(#"^(0[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9] (am|pm|AM|PM)$",
ErrorMessage = "Invalid Time.")]
Try this

Better!!!
public bool esvalida_la_hora(string thetime)
{
Regex checktime = new Regex("^(?:0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$");
if (!checktime.IsMatch(thetime))
return false;
if (thetime.Trim().Length < 5)
thetime = thetime = "0" + thetime;
string hh = thetime.Substring(0, 2);
string mm = thetime.Substring(3, 2);
int hh_i, mm_i;
if ((int.TryParse(hh, out hh_i)) && (int.TryParse(mm, out mm_i)))
{
if ((hh_i >= 0 && hh_i <= 23) && (mm_i >= 0 && mm_i <= 59))
{
return true;
}
}
return false;
}

public bool IsTimeString(string ts)
{
if (ts.Length == 5 && ts.Contains(':'))
{
int h;
int m;
return int.TryParse(ts.Substring(0, 2), out h)
&& int.TryParse(ts.Substring(3, 2), out m)
&& h >= 0 && h < 24
&& m >= 0 && m < 60;
}
else
return false;
}

Related

Conversion of TimeSpan to a new variable on HHH: mm

I am downloading the list of times from the database
var listaNadgodzinZPoprzMies = _ecpContext.Karta.Where(x => x.Login == userName && x.Rok == numerRoku && x.Miesiac < numerMiesiaca)
.Select(b => string.IsNullOrEmpty(b.SaldoNadgodzin) ? TimeSpan.Zero : TimeSpan.Parse(b.SaldoNadgodzin))
.ToList();
Adds all times
var sumaListaNadgodzinZPoprzMies = listaNadgodzinZPoprzMies.Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2);
And, I need to convert the number of minutes/ from the variable shown in the image (TimeSpan)
to string to format HHH:mm to other new variable
I scraped out these two functions some time ago in javascript ( I don't know how to convert them to c # ) (I don't know if it will work and whether it will be useful)
function msToTime(duration) {
const minutes = Math.floor((duration / (1000 * 60)) % 60), // 3.4 - 3, 3.5 - 3, 3.8 - 3
hours = Math.floor(duration / (1000 * 60 * 60));
return twoOrMoreDigits(hours) + ":" + twoOrMoreDigits(minutes);
}
function twoOrMoreDigits(n) {
return n < 10 ? '0' + n : n; // if (n < 10) { return '0' + n;} else return n;
}
anyone have any idea?
Here is an example:
TimeSpan time = new TimeSpan(200,1,23);
string strTime = $"{((int)time.TotalHours).ToString("D3")}:{time.Minutes.ToString("D2")}";
Console.WriteLine(strTime);
Output:
200:01
You want to format a timespan, you can achieve it by using this code:
var timespan = TimeSpan.FromMinutes(3180);
var result = timespan.ToString("hh:mm");
Console.WriteLine(result);
hh - hour in 24h format with leading zero
mm - minutes with leading zero
You can read more about timespan formatting here:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-timespan-format-strings

date range checking in C#

How to find if a date in the input is within a specific daterange (let's say for example wihtin last 7 days, meaning I will say -7). If it is within last 7 days, do something, else do something else.
I currently could do upto this, but I don't know how to change this further to meet what I want.
string a = "-1"; // These are values that are configurable based on which date is checked. Yesterday means, -1 for example.
string b = "-15"; // -15 means within last 15 days.
DateTime d = input;
DateTime e = d.AddDays(int.Parse(a));
if (d is between datetime.now and e)
{
//do something
}
else do something
First of all, use meaningful names instead of a and b, secondly: use proper data types (you don't use b at all):
int dayOffset = -1;
int lowerBound = -15;
var currentDate = DateTime.Now;
if(input >= currentDate.AddDays(dayOffset) && input <= currentDate)
{ // do smoething }
Using your names:
var currentDate = DateTime.Now;
if(input >= currentDate.AddDays(a) && input <= currentDate)
{ // do smoething }
You can use less than(<) and greater than(>) operator basicly.
I mean you should change your if conditionlike:
if (d >= e && d <= DateTime.Now)
You can try something like this to compare Date portion without Time
string a = "-1"; // These are values that are configurable based on which date is checked. Yesterday means, -1 for example.
string b = "-15"; // -15 means within last 15 days.
DateTime d = new DateTime();
DateTime e = d.AddDays(int.Parse(a));
if (DateTime.Now.Date >= d.Date && e.Date <= d.Date)
{
}

How to concatenate integer with string in C#?

I am developing a Console application for converting the time from 12 hours format to 24 hours format:
input: 02:03:34PM expected output:14:03:34
But I am getting 14:3:34
Below is my code snippet:
string[] arr_temp = Console.ReadLine().Split(':');
string time = arr_temp[2].ToUpper().Contains("AM") ? "AM" : "PM";
string sec=string.Empty;
for (int i = 0; i < 2; i++)
{
sec+= arr_temp[2][i];
}
int _hour = Int32.Parse(arr_temp[0])==0?0: Int32.Parse(arr_temp[0]);
int _minute = Int32.Parse(arr_temp[1]) == 0 ? 0 : Int32.Parse(arr_temp[1]);
int _sec = Int32.Parse(sec)==0?0: Int32.Parse(sec);
_hour = (time == "PM") ? _hour += 12 : _hour += 0;
_hour = (_hour < 10) ? '0' + _hour : _hour;
_minute = (_minute < 10) ? '0' + _minute : _minute;
_sec = (_sec < 10) ? '0' + _sec : _sec;
I am not getting the expected output.
Please suggest.
Seems a bit complicated to me as there's a much simpler way to display your DateTime variable to either 12 or 24 hours format.
First you will have to convert your string to a valid DateTime object. There are parsing methods which you can use, but you will have first to validate the input string returned by the user as a valid date.
Use the following code in order to convert your string to DateTime:
string dateString = "03/01/2009 10:00 AM";
DateTime date = DateTime.Parse(dateString);
DateTime.Parse will throw an exception if input string is not in the right format. In order to make sure this doesn't happen, use DateTime.TryParse instead.
string dateString = "03/01/2009 10:00 AM";
DateTime dateTime;
if (DateTime.TryParse(dateString , out dateTime))
{
Console.WriteLine(dateTime);
}
Then you can display the DateTime variable and format it the way you want.
DateTime dateTime = DateTime.Now;
string str12Format = dateTime.ToString("hh:mm:ss tt"); //12 hours format
string str24Format = dateTime.ToString("HH:mm:ss tt"); //24 hours format
_hour in your code is an integer. You cannot concatenate string to an integer. But the reverse is possible.
So you should use this instead :
int _hour = Int32.Parse(arr_temp[0])==0?0: Int32.Parse(arr_temp[0]);
int _minute = Int32.Parse(arr_temp[1]) == 0 ? 0 : Int32.Parse(arr_temp[1]);
int _sec = Int32.Parse(sec)==0?0: Int32.Parse(sec);
_hour = (time == "PM") ? _hour += 12 : _hour += 0;
String _hourS = (_hour < 10) ? '0' + _hour : _hour;
String _minuteS = (_minute < 10) ? '0' + _minute : _minute;
Try using DateTime.TryParseExact followed by ToString, do not repeat Microsoft and reinvent the wheel:
string source = Console.ReadLine();
DateTime date;
// DateTime.TryParseExact supports many formats; that's why "12:34AM" will be accepted
// DateTimeStyles.AllowWhiteSpaces let us be nice and allow, say "11 : 34 : 47 PM"
if (DateTime.TryParseExact(
source,
new string[] {"h:m:stt" , "h:mtt", "htt", "H:m:s", "H:m", "H"},
CultureInfo.InvariantCulture, // or CultureInfo.CurrentCulture
DateTimeStyles.AssumeLocal | DateTimeStyles.AllowWhiteSpaces,
out date))
Console.WriteLine(date.ToString("HH:mm:ss"));
else
Console.WriteLine($"Sorry, {source} is not a valid date");
Just pass you input
public static TimeSpan ConvertToAMPM(DateTime date)
{
return TimeSpan.Parse(date.ToString("h:mm tt",
CultureInfo.InvariantCulture));
}
public static TimeSpan ConvertTo24Hour(string time)
{
var cultureSource = new CultureInfo("en-US", false);
var cultureDest = new CultureInfo("de-DE", false);
var dt = DateTime.Parse(time, cultureSource);
return TimeSpan.Parse(dt.ToString("t", cultureDest));
}
The other answers so far mostly address the example of handling a DateTime, but they do not explain why your code breaks.
What you are trying to do is to add a leading zero to an int variable just as you'd do it with a string.
The problem is that the internal representation of an int is just the number itself, and it carries no format information. As such, it cannot store information about leading zeros. This can only be done by using string, which do not represent a number but a collection of characters.
So the essence is that you need to see the data and its representation as two separate things. In general it's best to keep the data in its native form and only convert it at the very last moment when needed for display. This also allows you to respect cultural differences of the display representation.
Many basic data types (including int and DateTime etc.) are formattable. What this means is that they can be converted to a string (display) representation with respect to a pattern describing how this representation should be. For int, such a pattern can define that it needs to have a leading zero like so:
string _hourDisplay = _hour.ToString("00");
Hi Nishank, Use this code :
string[] arr_temp = Console.ReadLine().Split(':');
string time = arr_temp[2].ToUpper().Contains("AM") ? "AM" : "PM";
string sec = arr_temp[2].Substring(0, 2);
string _hour = "";
if (time == "PM" && Int32.Parse(arr_temp[0]) < 12)
_hour = (Int32.Parse(arr_temp[0]) + 12).ToString("D2");
else if (time == "AM" && Int32.Parse(arr_temp[0]) == 12)
_hour = "00";
else
_hour = Int32.Parse(arr_temp[0]).ToString("D2");
string _minute = Int32.Parse(arr_temp[1]) == 0 ? "00" : Int32.Parse(arr_temp[1]).ToString("D2");
string _sec = Int32.Parse(sec) == 0 ? "00" : Int32.Parse(sec).ToString("D2");
string outputTime = _hour + ":" + _minute + ":" + _sec + "" + time;

Counting regular working days in a given period of time

need some help. I need to count regular working days for a given date period, for example, in our country, we have 5 regular working days monday to friday, then in code i need to exclude saturdays and sundays when I use it on my computations.
I need an algorithm something like this in C#:
int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
{
int nonWorkingDays = ((endDate - startDate) % 7) * 2;
return (endDate - startDate) - nonWorkingDays;
}
I know my draft is way way off :(. Thanks in advance. =)
PS: Guys please up-vote the best/fastest/most efficient answer below. Thanks =)
Check out this example on Code Project that uses a very efficient way that doesn't involve any looping ;)
It uses this alogrithm:
Calculate the number of time span in terms of weeks. Call it, W.
Deduct the first week from the number of weeks. W= W-1
Multiply the number of weeks with the number of working days per
week. Call it, D.
Find out the holidays during the specified time span. Call it, H.
Calculate the days in the first week. Call it, SD.
Calculate the days in the last week. Call it, ED.
Sum up all the days. BD = D + SD + ED - H.
One-liner!
int workingDays = Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)).Select(i=>new [] { DayOfWeek.Saturday, DayOfWeek.Sunday }.Contains(startDate.AddDays(i).DayOfWeek) ? 0 : 1).Sum();
Or more efficient:
DayOfWeek currDay = startDate.DayOfWeek;
int nonWorkingDays = 0;
foreach(var i in Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)))
{
if(currDay == DayOfWeek.Sunday || currDay == DayOfWeek.Saturday)
nonWorkingDays++;
if((int)++currDay > 6) currDay = (DayOfWeek)0;
}
I wrote a type extender to allow me to add (or subtract) weekdays to a given date. Maybe this will help you. Works great, so please vote for my post if this helped you.
/// <summary>
/// Adds weekdays to date
/// </summary>
/// <param name="value">DateTime to add to</param>
/// <param name="weekdays">Number of weekdays to add</param>
/// <returns>DateTime</returns>
public static DateTime AddWeekdays(this DateTime value, int weekdays)
{
int direction = Math.Sign(weekdays);
int initialDayOfWeek = Convert.ToInt32(value.DayOfWeek);
//---------------------------------------------------------------------------
// if the day is a weekend, shift to the next weekday before calculating
if ((value.DayOfWeek == DayOfWeek.Sunday && direction < 0)
|| (value.DayOfWeek == DayOfWeek.Saturday && direction > 0))
{
value = value.AddDays(direction * 2);
weekdays += (direction * -1); // adjust days to add by one
}
else if ((value.DayOfWeek == DayOfWeek.Sunday && direction > 0)
|| (value.DayOfWeek == DayOfWeek.Saturday && direction < 0))
{
value = value.AddDays(direction);
weekdays += (direction * -1); // adjust days to add by one
}
//---------------------------------------------------------------------------
int weeksBase = Math.Abs(weekdays / 5);
int addDays = Math.Abs(weekdays % 5);
int totalDays = (weeksBase * 7) + addDays;
DateTime result = value.AddDays(totalDays * direction);
//---------------------------------------------------------------------------
// if the result is a weekend, shift to the next weekday
if ((result.DayOfWeek == DayOfWeek.Sunday && direction > 0)
|| (result.DayOfWeek == DayOfWeek.Saturday && direction < 0))
{
result = result.AddDays(direction);
}
else if ((result.DayOfWeek == DayOfWeek.Sunday && direction < 0)
|| (result.DayOfWeek == DayOfWeek.Saturday && direction > 0))
{
result = result.AddDays(direction * 2);
}
//---------------------------------------------------------------------------
return result;
}
Not very fast, but this will do the trick:
int GetRegularWorkingDays(DateTime start, DateTime end)
{
return (
from day in Range(start, end)
where day.DayOfWeek != DayOfWeek.Saturday
where day.DayOfWeek != DayOfWeek.Sunday
select day).Count();
}
IEnumerable<DateTime> Range(DateTime start, DateTime end)
{
while (start <= end)
{
yield return start;
start = start.AddDays(1);
}
}
You could try a simple method of just counting the days. If this is usually done for periods of time like months and not years and isn't called repeatedly then this will not be a performance hit to just walk it.
int GetWorkingDays(DateTime startDate, DateTime endDate)
{
int count = 0;
for (DateTime currentDate = startDate; currentDate < endDate; currentDate = currentDate.AddDays(1))
{
if (currentDate.DayOfWeek == DayOfWeek.Sunday || currentDate.DayOfWeek == DayOfWeek.Saturday)
{
continue;
}
count++;
}
return count;
}
You could do it with a time line helper class - this class also allows for other intervals:
public class TimeLine
{
public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval) {
return TimeLine.CreateTimeLine(start, interval, DateTime.MaxValue);
}
public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval, DateTime end) {
var currentVal = start;
var endVal = end.Subtract(interval);
do {
currentVal = currentVal.Add(interval);
yield return currentVal;
} while (currentVal <= endVal);
}
}
To solve your problem you can do the following:
var workingDays = TimeLine.CreateTimeLine(DateTime.Now.Date, TimeSpan.FromDays(1), DateTime.Now.Date.AddDays(30))
.Where(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
var noOfWorkingDays = workingDays.Count();
This time line class can be used for any continuous time line of any interval.
Simple method to get work days:
int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
{
int total = 0;
if (startDate < endDate)
{
var days = endDate - startDate;
for( ; startDate < endDate; startDate = startDate.AddDays(1) )
{
switch(startDate.DayOfWeek)
{
case DayOfWeek.Saturday :
case DayOfWeek.Sunday :
break;
default:
total++;
break;
}
}
}
return total;
}
int count = 0;
switch (dateTimePicker2.Value.DayOfWeek.ToString())
{
case "Saturday": count--; break;
case "Sunday": count--; break;
default:break;
}
switch (dateTimePicker3.Value.DayOfWeek.ToString())
{
case "Saturday": count--; break;
case "Sunday": count--; break;
default:break;
}
if (count == -2)
count = -1;
int weeks = t.Days / 7;
int daycount =count+ t.Days - (2 * weeks)+1;
label7.Text = "No of Days : " + daycount.ToString();

DateTime.Compare how to check if a date is less than 30 days old?

I'm trying to work out if an account expires in less than 30 days. Am I using DateTime Compare correctly?
if (DateTime.Compare(expiryDate, now) < 30)
{
matchFound = true;
}
Am I using DateTime Compare correctly?
No. Compare only offers information about the relative position of two dates: less, equal or greater. What you want is something like this:
if ((expiryDate - DateTime.Now).TotalDays < 30)
matchFound = true;
This subtracts two DateTimes. The result is a TimeSpan object which has a TotalDays property.
Additionally, the conditional can be written directly as:
bool matchFound = (expiryDate - DateTime.Now).TotalDays < 30;
No if needed.
Alternatively, you can avoid naked numbers by using TimeSpan.FromDays:
bool matchFound = (expiryDate - DateTime.Now) < TimeSpan.FromDays(30);
This is slightly more verbose but I generally recommend using the appropriate types, and the appropriate type in this case is a TimeSpan, not an int.
should be
matchFound = (expiryDate - DateTime.Now).TotalDays < 30;
note the total days
otherwise you'll get werid behaviour
Well I would do it like this instead:
TimeSpan diff = expiryDate - DateTime.Today;
if (diff.Days > 30)
matchFound = true;
Compare only responds with an integer indicating weather the first is earlier, same or later...
Try this instead
if ( (expiryDate - DateTime.Now ).TotalDays < 30 ) {
matchFound = true;
}
Compare returns 1, 0, -1 for greater than, equal to, less than, respectively.
You want:
if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(30)) <= 0)
{
bool matchFound = true;
}
This will give you accurate result :
if ((expiryDate.Date - DateTime.Now.Date).Days < 30)
matchFound = true;
Assuming you want to assign false (if applicable) to matchtime, a simpler way of writing it would be..
matchtime = ((expiryDate - DateTime.Now).TotalDays < 30);
No, the Compare function will return either 1, 0, or -1. 0 when the two values are equal, -1 and 1 mean less than and greater than, I believe in that order, but I often mix them up.
No you are not using it correctly.
See here for details.
DateTime t1 = new DateTime(100);
DateTime t2 = new DateTime(20);
if (DateTime.Compare(t1, t2) > 0) Console.WriteLine("t1 > t2");
if (DateTime.Compare(t1, t2) == 0) Console.WriteLine("t1 == t2");
if (DateTime.Compare(t1, t2) < 0) Console.WriteLine("t1 < t2");
What you want to do is subtract the two DateTimes (expiryDate and DateTime.Now). This will return an object of type TimeSpan. The TimeSpan has a property "Days". Compare that number to 30 for your answer.
No it's not correct, try this :
DateTime expiryDate = DateTime.Now.AddDays(-31);
if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(-30)) < 1)
{
matchFound = true;
}
Actually none of these answers worked for me. I solved it by doing like this:
if ((expireDate.Date - DateTime.Now).Days > -30)
{
matchFound = true;
}
When i tried doing this:
matchFound = (expiryDate - DateTime.Now).Days < 30;
Today, 2011-11-14 and my expiryDate was 2011-10-17 i got that matchFound = -28. Instead of 28. So i inversed the last check.
// this isn't set up for good processing.
//I don't know what data set has the expiration
//dates of your accounts. I assume a list.
// matchfound is a single variablethat returns true if any 1 record is expired.
bool matchFound = false;
DateTime dateOfExpiration = DateTime.Today.AddDays(-30);
List<DateTime> accountExpireDates = new List<DateTime>();
foreach (DateTime date in accountExpireDates)
{
if (DateTime.Compare(dateOfExpiration, date) != -1)
{
matchFound = true;
}
}
You can try to do like this:
var daysPassed = (DateTime.UtcNow - expiryDate).Days;
if (daysPassed > 30)
{
// ...
}
Compare is unnecessary, Days / TotalDays are unnecessary.
All you need is
if (expireDate < DateTime.Now) {
// has expired
} else {
// not expired
}
note this will work if you decide to use minutes or months or even years as your expiry criteria.

Categories