fortran-lang / stdlib

Fortran Standard Library
https://stdlib.fortran-lang.org
MIT License
1.05k stars 164 forks source link

[Proposal] add `time_stamp` function and `stdlib_time` module: get formatted now time information? #464

Open zoziha opened 3 years ago

zoziha commented 3 years ago

Description For example, the Go language standard library has a time library golang/time, and stdlib also has a time module requirement. Is it possible to provide basic time module capabilities for stdlib. Start stdlib_time module by implementing a time_stamp function ?

Prior Art

Fortran Time Packages

Related Issues https://github.com/fortran-lang/stdlib/issues/1 and https://github.com/fortran-lang/stdlib/issues/106

ivan-pi commented 3 years ago

The codes of John Burkardt all contain a timestamp subroutine (GPL-licensed) with fixed format:

subroutine timestamp() ```fortran subroutine timestamp ( ) !*****************************************************************************80 ! !! TIMESTAMP prints the current YMDHMS date as a time stamp. ! ! Example: ! ! 31 May 2001 9:45:54.872 AM ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 18 May 2013 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! None ! implicit none character ( len = 8 ) ampm integer ( kind = 4 ) d integer ( kind = 4 ) h integer ( kind = 4 ) m integer ( kind = 4 ) mm character ( len = 9 ), parameter, dimension(12) :: month = (/ & 'January ', 'February ', 'March ', 'April ', & 'May ', 'June ', 'July ', 'August ', & 'September', 'October ', 'November ', 'December ' /) integer ( kind = 4 ) n integer ( kind = 4 ) s integer ( kind = 4 ) values(8) integer ( kind = 4 ) y call date_and_time ( values = values ) y = values(1) m = values(2) d = values(3) h = values(5) n = values(6) s = values(7) mm = values(8) if ( h < 12 ) then ampm = 'AM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Noon' else ampm = 'PM' end if else h = h - 12 if ( h < 12 ) then ampm = 'PM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Midnight' else ampm = 'AM' end if end if end if write ( *, '(i2,1x,a,1x,i4,2x,i2,a1,i2.2,a1,i2.2,a1,i3.3,1x,a)' ) & d, trim ( month(m) ), y, h, ':', n, ':', s, '.', mm, trim ( ampm ) return end ```

On the other hand the M_time module has a formatted time function:

function fmtdate(values,format) RESULT (timestr) ``` program demo_fmtdate use M_time, only : fmtdate implicit none integer :: dat(8) call date_and_time(values=dat) write(*,*)fmtdate(dat,"current date: %w, %l %d, %Y %H:%m:%s %N") call showme() contains subroutine showme() use M_time, only : fmtdate_usage call fmtdate_usage() ! see all formatting options end subroutine showme end program demo_fmtdate ```

Here are some options from other languages:

Some open issues to discuss are:

ivan-pi commented 3 years ago

Perhaps this is a bad idea, but I wonder if there is any advantage to write into the format string directly?

integer :: dat(8)
call date_and_time(values=dat)
write(*,fmtdate(dat))
! vs
write(*,'(A)') datestr(dat)
milancurcic commented 3 years ago

Somewhat related is #106.

Rather than implementing a specific (fixed-format) time stamp, I recommend simply providing a binding to C strftime, which is a much more versatile solution with less code.

The Forlab implementation looks like it was adapted from John Burkardt's. timestamp(). Should probably note that in the Forlab LICENSE file.

zoziha commented 3 years ago

The Forlab implementation looks like it was adapted from John Burkardt's. timestamp(). Should probably note that in the Forlab LICENSE file.

Thanks for reminding. I have only come into contact with open source code not long ago, and have not been very familiar with open source licenses. If it is a relatively short function, do I need to follow its license because I changed it? Can a project simply combine multiple open source licenses?

nncarlson commented 3 years ago

do I need to follow its license because I changed it?

Absolutely. Adopting the same interface is okay, I believe, but you have to respect the license when it comes to the implementation. That's why looking too closely at GPL code for the standard library isn't such a good idea IMO. The standard library is aiming for MIT or BSD licensing isn't it?

zoziha commented 3 years ago

I'm very sorry about that, I didn't realize this before. John Burkardt/timestamp was a subroutine, but now forlab/times_stamp becomes a module function. Isn’t it OK? I made this git push today, can I remove this license issue by just deleting this LGPL code git push? (I am scared😢, I just deleted it just now.)

zoziha commented 3 years ago

How about simply creating a fixed format time_stamp function to start stdlib_time. It's simple, but it's also useful. This reminds people that there is still some work in stdlib_time, remember to improve stdlib_time. 😂

ivan-pi commented 3 years ago

How about simply creating a fixed format time_stamp function to start stdlib_time. It's simple, but it's also useful.

NAG has a simple function called nagf_time_date_array_string that takes as input an integer :: itime(7) (kind of similar to the return value of subroutine date_and_time and returns a formatted string.

If we can reach an agreement on the name and format I'm fine to have this. But in general the solution of @milancurcic will be more helpful. A downside of c_strftime is one needs to size the buffer correctly. If we could have function which returns a character(len=:), allocatable and accepts a custom format it would be more convenient. Then everyone can have the format they likes best and write a simple wrapper function

function nowstr()
character(len=:), allocatable :: nowstr
integer :: vals(8)
call date_and_time(values=vals)
! %c returns a date and time representation like:
! Sun Aug 19 02:56:02 2012
nowstr = fstrftime('%c',vals) 
end function
awvwgk commented 2 years ago

I would have use for stdlib provided derived type to express a time stamp since it would allow to bridge TOML Fortran and stdlib. This would allow to directly retrieve TOML documents as stdlib hash map including date time values from the TOML document as stdlib compatible derived type.

jvdp1 commented 2 years ago

A (simple) time stamp is already implemented in stdlib_logger. Could it be an idea to move it to e.g., stdlib_time and discuss its API and implementation based on the different needs?