|
That's a lot of code for something the framework already does for you.
public static string TimeConverter(string time)
{
if (!DateTime.TryParseExact(time, "h:mmtt", CultureInfo.InvariantCulture, DateTimeStyles.None, out var value))
{
return string.Empty;
}
return value.ToString("HH:mm:ss", CultureInfo.InvariantCulture);
} DateTime.TryParseExact Method (System) | Microsoft Docs[^]
Custom date and time format strings | Microsoft Docs[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
down-voted
This question, like others you have posted, suggests a pattern where you "throw mud against the wall to see what sticks," and, then, when nothing sticks, you ask other people to sort out your mess.
You need to start doing some research and study before you make code-salad: you should have learned how String.Format works, and what the format options are that specify the desired transformation, from the answers to your previous question.
In the future, in "the real world," if you are ever employed as a programmer, do you think your employer would tolerate your wasting their time ?
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Others have answered your conversion question but I'm curious as to why you are trying to do this on thousands of rows. Normally, showing AM/PM is a display issue so would be handled when displaying the relevant item. If that's the case, it's generally a bad idea to try and display thousands of items.
|
|
|
|
|
This is a part of the calculation procedure in my project. I need to calculate time differences between two dates (along with times)) and automate the process.
|
|
|
|
|
How is the data stored? Because if it's in DateTime already there is no need to try and convert anything.
|
|
|
|
|
And we come back to the same argument that has been presented to you many times - DON'T STORE YOU DATES AS STRINGS.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Store the date as a date and your problem goes away altogether. A decision to use strings to represent dates is causing you unnecessary pain here; there's a DateTime datatype for a reason, use that. Think about it, you wouldn't store numbers as strings would you, so why store dates as strings?
|
|
|
|
|
Pete O'Hanlon wrote: you wouldn't store numbers as strings would you?
That may be a very brave assumption.
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
Hi,
I want to convert date formatted in yyyy/M/d to yyyy/MM/dd.
Is there any short way to do?
For example: 1400/6/7 to 1400/06/07
|
|
|
|
|
The first thing to clarify is whether you are dealing with a DateTime obtained by use of the Persian Calendar class: System.Globalization.PersianCalendar
... or, are you dealing with a run-time DateTime value on a computer where the OS is using the Persian Calendar as the default ?
Possible resources: Noda Time [^] and [^]
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I use
System.Globalization.PersianCalendar
|
|
|
|
|
Okay, then is the formatting you want done on a machine using Persian Calendar as the default ?
If yes, then can't standard ToString Format syntax (as used in Farsi ?) give you what you want ?
DateTime dt = new DateTime(1400, 6, 7);
string fmt = dt.ToString("yyyy/MM/dd");
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Thanks, If I use this code to iterate through hundreds of datatable rows, would it consume more memory due to the instantiation?
|
|
|
|
|
DateTime is a value type, so it won't allocate anything on the heap.
The ToString call will allocate a string on the heap. But if you want to display the date to the user, then it has to be converted to a string at some point.
Without knowing precisely what you're trying to do, we can't really tell you how to optimise it.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: The ToString call will allocate a string on the heap. But if you want to display the date to the user, then it has to be converted to a string at some point. Hi, Richard, I am trying to understand this statement: I think you are making a distinction I am missing ... perhaps you are referring to (first) a pointer to the "raw bytes" on the heap ... compared to them bytes morphed into ascii format for display usage ?
Curious what you think of Skeet's format work-around for optimizing string conversion (link in my last message to Alex ... below).
As always, I look forward to your response.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I was simply referring to the fact that a DateTime is a value type, whereas String is a reference type. Allocation of value types tends to be "cheaper" than reference types.
Jon's workaround is good, but could be improved in .NET Core 2.1, or even in .NET Framework 4.7.2+ with a reference to the System.Memory package and a couple of helpers defined.
#if NETSTANDARD2_0
namespace System.Buffers
{
public delegate void SpanAction<T, in TArg>(Span<T> span, TArg arg);
}
#endif
static class StringHelpers
{
public static string Create<TArg>(int length, TArg state, SpanAction<char, TArg> action)
{
if (length < 0) throw new ArgumentOutOfRangeException(nameof(length));
if (action is null) throw new ArgumentNullException(nameof(action));
if (length == 0) return string.Empty;
#if NETSTANDARD2_0
unsafe
{
var str = new string('\0', length);
fixed (char* chars = str)
{
var span = new Span<char>(chars, length);
action(span, state);
}
return str;
}
#else
return string.Create(length, state, action);
#endif
}
}
public static string FormatDateTime(DateTime dt) => StringHelpers.Create(21, dt, static (buffer, date) =>
{
int value = date.Day;
buffer[0] = (char)('0' + (value / 10));
buffer[1] = (char)('0' + (value % 10));
buffer[2] = '.';
value = date.Month;
buffer[3] = (char)('0' + (value / 10));
buffer[4] = (char)('0' + (value % 10));
buffer[5] = '.';
value = date.Year;
buffer[6] = (char)('0' + ((value / 10) % 10));
buffer[7] = (char)('0' + (value % 10));
buffer[8] = ' ';
value = date.Hour;
buffer[9] = (char)('0' + (value / 10));
buffer[10] = (char)('0' + (value % 10));
buffer[11] = ':';
value = date.Minute;
buffer[12] = (char)('0' + (value / 10));
buffer[13] = (char)('0' + (value % 10));
buffer[14] = ':';
value = date.Second;
buffer[15] = (char)('0' + (value / 10));
buffer[16] = (char)('0' + (value % 10));
buffer[17] = ':';
value = date.Millisecond;
buffer[18] = (char)('0' + ((value / 100) % 10));
buffer[19] = (char)('0' + ((value / 10) % 10));
buffer[20] = (char)('0' + (value % 10));
}); Rather than allocating a new 21-character char array on every call, and then having the string constructor copy that array to its internal storage, this new version writes the values directly to the string 's internal storage. It does have to allocate a delegate for the SpanAction , but since it's a static lambda, that only happens once per AppDomain.
If you're using .NET Core 2.1 or later, or .NET 5, you can drop the helpers and just use string.Create directly.
Creating Strings with No Allocation Overhead Using String.Create - Steve Gordon - Code with Steve[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
modified 22-Sep-21 5:23am.
|
|
|
|
|
Excellent ! I hope you'll publish this in an article, or a Tip/Trick.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I think your code is missing the 'state' parameter.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
No - dt is the state parameter, and is referenced as date in the lambda method.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi, in the scope of your class StringHelpers: return string.Create(length, state, action); 'state is referenced, but is never defined. In the code in Steve Gordon's article, 'state is defined.
public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action); My eyesight is terrible; as the doofus detective says in police procedural movies: "what am i missing ?"
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Whoops! The parameter arg should have been called state .
That should be fixed now.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Knowing you are not quite perfect makes me feel a little more secure, but, in no way diminishes my respect for your technical excellence
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Alex Dunlop wrote: would it consume more memory due to the instantiation? Hi, I think to answer that clearly one would need to know the database, its internal format, etc., and the nature of your query that returns (I assume) some subset of rows. I don't have the expertise in this area to be more helpful.
But, yes, creating strings has a cost; here's an idea from uber-guru Jon Skeet you might try: [^]
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
This is my data on which a LINQ query executed. i have bit confusion about LINQ grouping used there. here is sample code.
List<Data> _data = new List<Data>
{
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "205.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = "222.30"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "784.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "555.00"
},
};
var periods = _data.Select(y => y.Period).Distinct().OrderBy(y => y).ToArray();
var results =
_data
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
.Select(x => new
{
x.Key,
Lookup = x.ToLookup(y => y.Period, y => y.PeriodValue),
})
.Select(x => new
{
x.Key.Section,
x.Key.Lineitem,
x.Key.BrokerCode,
x.Key.BrokerName,
Map = periods.ToDictionary(y => y, y => String.Join("|", x.Lookup[y])),
})
.ToArray();
var dt = new DataTable();
dt.Columns.Add("Section");
dt.Columns.Add("Lineitem");
dt.Columns.Add("BrokerCode");
dt.Columns.Add("BrokerName");
foreach (var period in periods)
{
dt.Columns.Add(period);
}
foreach (var result in results)
{
string[] key_values = new string[]
{
result.Section,
result.Lineitem,
result.BrokerCode,
result.BrokerName,
};
string[] period_values = periods.Select(p => result.Map[p]).ToArray()
dt.Rows.Add(key_values.Concat(period_values).ToArray());
}
i have to group on few fields and those are Section, LineItem, BrokerCode and Period but a guy does the grouping like this way
var results =
_data
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
.Select(x => new
{
x.Key,
Lookup = x.ToLookup(y => y.Period, y => y.PeriodValue),
})
.Select(x => new
{
x.Key.Section,
x.Key.Lineitem,
x.Key.BrokerCode,
x.Key.BrokerName,
Map = periods.ToDictionary(y => y, y => String.Join("|", x.Lookup[y])),
})
.ToArray();
So my question is what kind of grouping is it.... see the below grouping code.
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
Is it two set of grouping ? one set is { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName }
and another set is { x.Period, x.PeriodValue } ?
please guide me how the above grouping will be working ?
Thanks
|
|
|
|
|
|