Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special case DateTime/TimeSpan in Format-Custom #18142

Open
powercode opened this issue Sep 21, 2022 · 6 comments
Open

Special case DateTime/TimeSpan in Format-Custom #18142

powercode opened this issue Sep 21, 2022 · 6 comments
Assignees
Labels
Issue-Enhancement the issue is more of a feature request than a bug WG-Interactive-Console the console experience

Comments

@powercode
Copy link
Collaborator

powercode commented Sep 21, 2022

Produce one-line output in Format-Custom for DateTime by default

Dates and times get really spammy in Format-Custom

This simple object with a datetime

[pscustomobject]@{Time = [datetime]::now} | format-custom

produces 148 lines of output!


class PSCustomObject
{
  Time = 
    class DateTime
    {
      Date = 
        class DateTime
        {
          Date = 
            class DateTime
            {
              Date = 
                class DateTime
                {
                  Date = 
                    class DateTime
                    {
                      Date = 2022-09-21 00:00:00
                      Day = 21
                      DayOfWeek = Wednesday
                      DayOfYear = 264
                      Hour = 0
                      Kind = Local
                      Millisecond = 0
                      Minute = 0
                      Month = 9
                      Second = 0
                      Ticks = 637993152000000000
                      TimeOfDay = 00:00:00
                      Year = 2022
                      DateTime = den 21 september 2022 00:00:00
                    }
                  Day = 21
                  DayOfWeek = Wednesday
                  DayOfYear = 264
                  Hour = 0
                  Kind = Local
                  Millisecond = 0
                  Minute = 0
                  Month = 9
                  Second = 0
                  Ticks = 637993152000000000
                  TimeOfDay = 
                    class TimeSpan
                    {
                      Ticks = 0
                      Days = 0
                      Hours = 0
                      Milliseconds = 0
                      Minutes = 0
                      Seconds = 0
                      TotalDays = 0
                      TotalHours = 0
                      TotalMilliseconds = 0
                      TotalMinutes = 0
                      TotalSeconds = 0
                    }
                  Year = 2022
                  DateTime = den 21 september 2022 00:00:00
                }
              Day = 21
              DayOfWeek = Wednesday
              DayOfYear = 264
              Hour = 0
              Kind = Local
              Millisecond = 0
              Minute = 0
              Month = 9
              Second = 0
              Ticks = 637993152000000000
              TimeOfDay = 
                class TimeSpan
                {
                  Ticks = 0
                  Days = 0
                  Hours = 0
                  Milliseconds = 0
                  Minutes = 0
                  Seconds = 0
                  TotalDays = 0
                  TotalHours = 0
                  TotalMilliseconds = 0
                  TotalMinutes = 0
                  TotalSeconds = 0
                }
              Year = 2022
              DateTime = den 21 september 2022 00:00:00
            }
          Day = 21
          DayOfWeek = Wednesday
          DayOfYear = 264
          Hour = 0
          Kind = Local
          Millisecond = 0
          Minute = 0
          Month = 9
          Second = 0
          Ticks = 637993152000000000
          TimeOfDay = 
            class TimeSpan
            {
              Ticks = 0
              Days = 0
              Hours = 0
              Milliseconds = 0
              Minutes = 0
              Seconds = 0
              TotalDays = 0
              TotalHours = 0
              TotalMilliseconds = 0
              TotalMinutes = 0
              TotalSeconds = 0
            }
          Year = 2022
          DateTime = den 21 september 2022 00:00:00
        }
      Day = 21
      DayOfWeek = Wednesday
      DayOfYear = 264
      Hour = 9
      Kind = Local
      Millisecond = 945
      Minute = 36
      Month = 9
      Second = 31
      Ticks = 637993497919455174
      TimeOfDay = 
        class TimeSpan
        {
          Ticks = 345919455174
          Days = 0
          Hours = 9
          Milliseconds = 945
          Minutes = 36
          Seconds = 31
          TotalDays = 0,400369739784722
          TotalHours = 9,60887375483333
          TotalMilliseconds = 34591945,5174
          TotalMinutes = 576,53242529
          TotalSeconds = 34591,9455174
        }
      Year = 2022
      DateTime = den 21 september 2022 09:36:31
    }
}

I suggest that we should special-case DateTime in the custom formatted to only print the string same string as we get when we limit the depth:

[pscustomobject]@{Obj = [PSCustomObject]@{Time = [datetime]::now}} | fc -Depth 1
class PSCustomObject
{
  Obj =
    class PSCustomObject
    {
      Time = 2022-09-21 09:38:35
    }
}

So that

[pscustomobject]@{Time = [datetime]::now} | format-custom

would output

class PSCustomObject
{
    Time = 2022-09-21 09:38:35
}

Maybe use -Force to get the full recursive version?

Proposed technical implementation details (optional)

No response

@powercode powercode added Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group. labels Sep 21, 2022
@SteveL-MSFT
Copy link
Member

You can see a more real world case with dir * | select -first 1 | format-custom which has a datetime property that does the same. I would agree that the current output is probably not as useful as rendering datetime as a single string. If we are special casing datetime only, then I don't like using the ambiguous -force to get current behavior and would prefer something like -expanddatetime.

@SteveL-MSFT SteveL-MSFT added the WG-Interactive-Console the console experience label Sep 26, 2022
@dkaszews
Copy link
Contributor

I don't like using the ambiguous -force to get current behavior and would prefer something like -expanddatetime.

+1 to that, -Force already has way too many different meanings, from obvious overwriting existing files in Move-Item to odd like showing hidden files in Get-ChildItem.

@powercode
Copy link
Collaborator Author

How about a more general parameter like -ExpandType:string[]?

# get single line date
dir | select -first 1 | format-custom 
# get way too much output
dir | select -first 1 | format-custom -ExpandType:System.Datetime, SomeFutureNoisyType

@powercode
Copy link
Collaborator Author

DateTime already has an entry for custom formatting, but it is not applied when datetime is a member.

        private static IEnumerable<FormatViewDefinition> ViewsOf_System_DateTime()
        {
            yield return new FormatViewDefinition("DateTime",
                CustomControl.Create()
                    .StartEntry()
                        .AddPropertyExpressionBinding(@"DateTime")
                    .EndEntry()
                .EndControl());
        }
[DateTime]::Now | format-custom

den 14 oktober 2022 09:51:00

powercode added a commit to powercode/PowerShell that referenced this issue Oct 14, 2022
@sdwheeler sdwheeler removed the Needs-Triage The issue is new and needs to be triaged by a work group. label Nov 8, 2023
@sdwheeler
Copy link
Collaborator

@JamesWTruher Can you provide an opinion here?

@JamesWTruher
Copy link
Member

There are some types in dotnet which have elements of recursion and datetime is one of those. Remember that the a new formatting frame is not added once you start rendering, so if you have format-custom with any dotnet type which is recursive then this may occur. We do, IIRC, have a limit to the depth that we render (I think it's 5), and it is settable with the -depth parameter. Perhaps this is something that could be used.

And, as you've noticed, In the non-custom formatting cases, we simply call the ToString on the member.

This is all for the relatively low use case of Format-Custom where specific formatting has not been created. It seems a relatively low impact case to me to expend much energy. Especially considering that it might be a bit complicated to generalize a solution for any case where the object has this recursive behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement the issue is more of a feature request than a bug WG-Interactive-Console the console experience
Projects
None yet
Development

No branches or pull requests

5 participants