bash - summarize day value to years, month, and left days

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
5
down vote

favorite












Is there any simple way to summarize a day value like (1327 days) to the format:



xx years; xx month; xx days


without having to use a separate variable for each value.

Preferably with one command.










share|improve this question



















  • 2




    Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
    – terdon♦
    Sep 25 '17 at 15:15






  • 1




    September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
    – Kusalananda
    Sep 25 '17 at 15:43











  • @terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
    – nath
    Sep 25 '17 at 16:12






  • 1




    Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
    – terdon♦
    Sep 25 '17 at 16:19







  • 1




    @nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
    – Kusalananda
    Sep 25 '17 at 18:24














up vote
5
down vote

favorite












Is there any simple way to summarize a day value like (1327 days) to the format:



xx years; xx month; xx days


without having to use a separate variable for each value.

Preferably with one command.










share|improve this question



















  • 2




    Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
    – terdon♦
    Sep 25 '17 at 15:15






  • 1




    September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
    – Kusalananda
    Sep 25 '17 at 15:43











  • @terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
    – nath
    Sep 25 '17 at 16:12






  • 1




    Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
    – terdon♦
    Sep 25 '17 at 16:19







  • 1




    @nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
    – Kusalananda
    Sep 25 '17 at 18:24












up vote
5
down vote

favorite









up vote
5
down vote

favorite











Is there any simple way to summarize a day value like (1327 days) to the format:



xx years; xx month; xx days


without having to use a separate variable for each value.

Preferably with one command.










share|improve this question















Is there any simple way to summarize a day value like (1327 days) to the format:



xx years; xx month; xx days


without having to use a separate variable for each value.

Preferably with one command.







bash date






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 25 '17 at 15:24

























asked Sep 25 '17 at 15:12









nath

633421




633421







  • 2




    Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
    – terdon♦
    Sep 25 '17 at 15:15






  • 1




    September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
    – Kusalananda
    Sep 25 '17 at 15:43











  • @terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
    – nath
    Sep 25 '17 at 16:12






  • 1




    Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
    – terdon♦
    Sep 25 '17 at 16:19







  • 1




    @nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
    – Kusalananda
    Sep 25 '17 at 18:24












  • 2




    Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
    – terdon♦
    Sep 25 '17 at 15:15






  • 1




    September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
    – Kusalananda
    Sep 25 '17 at 15:43











  • @terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
    – nath
    Sep 25 '17 at 16:12






  • 1




    Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
    – terdon♦
    Sep 25 '17 at 16:19







  • 1




    @nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
    – Kusalananda
    Sep 25 '17 at 18:24







2




2




Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
– terdon♦
Sep 25 '17 at 15:15




Not really. What month are you thinking of? Does it include February? Months can have 28, 29, 30 or 31 days. How can we convert an arbitrary number of days to months?
– terdon♦
Sep 25 '17 at 15:15




1




1




September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
– Kusalananda
Sep 25 '17 at 15:43





September of 1752 had 19 days in the US/UK/Canada. Calendars can be weird sometimes.
– Kusalananda
Sep 25 '17 at 15:43













@terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
– nath
Sep 25 '17 at 16:12




@terdon good point. The sollution I used now is: echo "1324 365" | awk 'printf "%.2f", $1 / $2' | awk -F'.' 'print $1 " years and " $2 " days"'
– nath
Sep 25 '17 at 16:12




1




1




Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
– terdon♦
Sep 25 '17 at 16:19





Yes, that will work if you don't care about leap years. Although if that's what you want, you may as well do it in one command: echo "1324 365" | awk 'y=sprintf("%.2f", $1 / $2); sub(/./, " years and ", y); print y,"days"'
– terdon♦
Sep 25 '17 at 16:19





1




1




@nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
– Kusalananda
Sep 25 '17 at 18:24




@nath You have to count from a date. The days of the months are to irregular to come up with a generic answer.
– Kusalananda
Sep 25 '17 at 18:24










2 Answers
2






active

oldest

votes

















up vote
9
down vote



accepted










For a duration that includes a number of months or years, that has to make reference to a particular date, as different months or different years have different lengths.



To know how many years/months/days from now to 1327 days from now, with dateutils:



$ ddiff -f '%Y years, %m months, %d days' today "$(dadd now 1327)"
3 years, 7 months, 19 days


(you may sometimes find ddiff available as datediff or dateutils.ddiff; same for dadd).



That's what I get now on 2017-09-25 (because that's from 2017-09-25 to 2021-05-14). If I were to run that on 2018-03-01, I'd get:



3 years, 7 months, 17 days


because that's from 2018-03-01 to 2021-10-18.



And on that 2018-03-01 day, 1327 days ago would give 3 years, 7 months, 16 days.



More info at How can I calculate and format a date duration using GNU tools, not a result date?






share|improve this answer





























    up vote
    3
    down vote













    I think that's a bit too complicated for a reasonably accurate solution (i. e. regarding calendar oddities like leap days) in Bash. Try something with a programming library for calendars like Python instead:



    #!/usr/bin/env python3
    import sys, calendar
    from datetime import *

    difference = timedelta(days=int(sys.argv[1]))
    now = datetime.now(timezone.utc).astimezone()
    then = now - difference

    years = now.year - then.year
    months = now.month - then.month
    days = now.day - then.day
    if days < 0:
    days += calendar.monthrange(then.year, then.month)[1]
    months -= 1
    if months < 0:
    months += 12
    years -= 1

    print(' year(s); month(s); day(s)'.format(years, months, days))


    Example invocation:



    $ ./human-redable-date-difference.py 1327
    3 year(s); 7 month(s); 19 day(s)


    Of course you can adjust the input and output format to your liking to select time differences based on other things than the number of days.






    share|improve this answer






















      Your Answer







      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "106"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f394334%2fbash-summarize-day-value-to-years-month-and-left-days%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      9
      down vote



      accepted










      For a duration that includes a number of months or years, that has to make reference to a particular date, as different months or different years have different lengths.



      To know how many years/months/days from now to 1327 days from now, with dateutils:



      $ ddiff -f '%Y years, %m months, %d days' today "$(dadd now 1327)"
      3 years, 7 months, 19 days


      (you may sometimes find ddiff available as datediff or dateutils.ddiff; same for dadd).



      That's what I get now on 2017-09-25 (because that's from 2017-09-25 to 2021-05-14). If I were to run that on 2018-03-01, I'd get:



      3 years, 7 months, 17 days


      because that's from 2018-03-01 to 2021-10-18.



      And on that 2018-03-01 day, 1327 days ago would give 3 years, 7 months, 16 days.



      More info at How can I calculate and format a date duration using GNU tools, not a result date?






      share|improve this answer


























        up vote
        9
        down vote



        accepted










        For a duration that includes a number of months or years, that has to make reference to a particular date, as different months or different years have different lengths.



        To know how many years/months/days from now to 1327 days from now, with dateutils:



        $ ddiff -f '%Y years, %m months, %d days' today "$(dadd now 1327)"
        3 years, 7 months, 19 days


        (you may sometimes find ddiff available as datediff or dateutils.ddiff; same for dadd).



        That's what I get now on 2017-09-25 (because that's from 2017-09-25 to 2021-05-14). If I were to run that on 2018-03-01, I'd get:



        3 years, 7 months, 17 days


        because that's from 2018-03-01 to 2021-10-18.



        And on that 2018-03-01 day, 1327 days ago would give 3 years, 7 months, 16 days.



        More info at How can I calculate and format a date duration using GNU tools, not a result date?






        share|improve this answer
























          up vote
          9
          down vote



          accepted







          up vote
          9
          down vote



          accepted






          For a duration that includes a number of months or years, that has to make reference to a particular date, as different months or different years have different lengths.



          To know how many years/months/days from now to 1327 days from now, with dateutils:



          $ ddiff -f '%Y years, %m months, %d days' today "$(dadd now 1327)"
          3 years, 7 months, 19 days


          (you may sometimes find ddiff available as datediff or dateutils.ddiff; same for dadd).



          That's what I get now on 2017-09-25 (because that's from 2017-09-25 to 2021-05-14). If I were to run that on 2018-03-01, I'd get:



          3 years, 7 months, 17 days


          because that's from 2018-03-01 to 2021-10-18.



          And on that 2018-03-01 day, 1327 days ago would give 3 years, 7 months, 16 days.



          More info at How can I calculate and format a date duration using GNU tools, not a result date?






          share|improve this answer














          For a duration that includes a number of months or years, that has to make reference to a particular date, as different months or different years have different lengths.



          To know how many years/months/days from now to 1327 days from now, with dateutils:



          $ ddiff -f '%Y years, %m months, %d days' today "$(dadd now 1327)"
          3 years, 7 months, 19 days


          (you may sometimes find ddiff available as datediff or dateutils.ddiff; same for dadd).



          That's what I get now on 2017-09-25 (because that's from 2017-09-25 to 2021-05-14). If I were to run that on 2018-03-01, I'd get:



          3 years, 7 months, 17 days


          because that's from 2018-03-01 to 2021-10-18.



          And on that 2018-03-01 day, 1327 days ago would give 3 years, 7 months, 16 days.



          More info at How can I calculate and format a date duration using GNU tools, not a result date?







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Sep 25 '17 at 19:35

























          answered Sep 25 '17 at 15:35









          Stéphane Chazelas

          284k53523860




          284k53523860






















              up vote
              3
              down vote













              I think that's a bit too complicated for a reasonably accurate solution (i. e. regarding calendar oddities like leap days) in Bash. Try something with a programming library for calendars like Python instead:



              #!/usr/bin/env python3
              import sys, calendar
              from datetime import *

              difference = timedelta(days=int(sys.argv[1]))
              now = datetime.now(timezone.utc).astimezone()
              then = now - difference

              years = now.year - then.year
              months = now.month - then.month
              days = now.day - then.day
              if days < 0:
              days += calendar.monthrange(then.year, then.month)[1]
              months -= 1
              if months < 0:
              months += 12
              years -= 1

              print(' year(s); month(s); day(s)'.format(years, months, days))


              Example invocation:



              $ ./human-redable-date-difference.py 1327
              3 year(s); 7 month(s); 19 day(s)


              Of course you can adjust the input and output format to your liking to select time differences based on other things than the number of days.






              share|improve this answer


























                up vote
                3
                down vote













                I think that's a bit too complicated for a reasonably accurate solution (i. e. regarding calendar oddities like leap days) in Bash. Try something with a programming library for calendars like Python instead:



                #!/usr/bin/env python3
                import sys, calendar
                from datetime import *

                difference = timedelta(days=int(sys.argv[1]))
                now = datetime.now(timezone.utc).astimezone()
                then = now - difference

                years = now.year - then.year
                months = now.month - then.month
                days = now.day - then.day
                if days < 0:
                days += calendar.monthrange(then.year, then.month)[1]
                months -= 1
                if months < 0:
                months += 12
                years -= 1

                print(' year(s); month(s); day(s)'.format(years, months, days))


                Example invocation:



                $ ./human-redable-date-difference.py 1327
                3 year(s); 7 month(s); 19 day(s)


                Of course you can adjust the input and output format to your liking to select time differences based on other things than the number of days.






                share|improve this answer
























                  up vote
                  3
                  down vote










                  up vote
                  3
                  down vote









                  I think that's a bit too complicated for a reasonably accurate solution (i. e. regarding calendar oddities like leap days) in Bash. Try something with a programming library for calendars like Python instead:



                  #!/usr/bin/env python3
                  import sys, calendar
                  from datetime import *

                  difference = timedelta(days=int(sys.argv[1]))
                  now = datetime.now(timezone.utc).astimezone()
                  then = now - difference

                  years = now.year - then.year
                  months = now.month - then.month
                  days = now.day - then.day
                  if days < 0:
                  days += calendar.monthrange(then.year, then.month)[1]
                  months -= 1
                  if months < 0:
                  months += 12
                  years -= 1

                  print(' year(s); month(s); day(s)'.format(years, months, days))


                  Example invocation:



                  $ ./human-redable-date-difference.py 1327
                  3 year(s); 7 month(s); 19 day(s)


                  Of course you can adjust the input and output format to your liking to select time differences based on other things than the number of days.






                  share|improve this answer














                  I think that's a bit too complicated for a reasonably accurate solution (i. e. regarding calendar oddities like leap days) in Bash. Try something with a programming library for calendars like Python instead:



                  #!/usr/bin/env python3
                  import sys, calendar
                  from datetime import *

                  difference = timedelta(days=int(sys.argv[1]))
                  now = datetime.now(timezone.utc).astimezone()
                  then = now - difference

                  years = now.year - then.year
                  months = now.month - then.month
                  days = now.day - then.day
                  if days < 0:
                  days += calendar.monthrange(then.year, then.month)[1]
                  months -= 1
                  if months < 0:
                  months += 12
                  years -= 1

                  print(' year(s); month(s); day(s)'.format(years, months, days))


                  Example invocation:



                  $ ./human-redable-date-difference.py 1327
                  3 year(s); 7 month(s); 19 day(s)


                  Of course you can adjust the input and output format to your liking to select time differences based on other things than the number of days.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Sep 27 '17 at 7:25

























                  answered Sep 25 '17 at 18:39









                  David Foerster

                  918616




                  918616



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f394334%2fbash-summarize-day-value-to-years-month-and-left-days%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Displaying single band from multi-band raster using QGIS

                      How many registers does an x86_64 CPU actually have?