3

My goal is to make fortran return the difference between two times that were passed in as character strings, very simular to VBA's TimeDiff. I've been going through the handling of date and time in fortran for quite a while now, but couldn't find what I need in this perticular case. The first problem in fortran is how to turn a string into a further computable time variable. time_and_dates ctime for example converts the time into a character string, but whats needed in my case is the exact opposite.

Since fortran easily calculates things like a spot watch for the time needed for a programm to finish and even dislays the time from the system itself, it obviously is able to calculate these kind of stuff if my thoughts are right so far.

But how to pass my String "YYYYMMDD HHMMSS" into the time format, how to calculate with it and how to phrase the output?

Here an example of where this should lead:

date1 = as.date("20130512 091519") !Stringinput
date2 = as.date("20131116 120418")


result = time.difference(date1,date2,outputunit="seconds")

print*, 'time diff in sec: ', result !returns something like 4646345 as Integer

Due to fortrans ability to do such calculations in other context (stop watch etc) I would really appreciate a solution that does not involve any extern extensions or adventurous manual coding (365 ...leap year... /400..and so on).

Is there a way to use the intern possibilies of fortran and the system (win64) for my purpose?

If not, on which way passes the system its time information into fortran and can this possibly be imitated (so the source isn't "system" but "character string" instead)?

EDIT: Thanks for the input so far, but as mentioned above I would preferably use fortrans intern abilities (as it happens in stop watch) for the job instead of extensions or manual calculations. I find it hard to belief that date&time can only be converted to character but not the other way round... but thank you anyway.

Kara
  • 6,115
  • 16
  • 50
  • 57
Stephen Rewitz
  • 43
  • 1
  • 2
  • 5
  • Fortran does not have wonderful intrinsic support for string manipulation and conversion to other types. So sometimes there is no other way than to implement those yourself. I edited my answer below, let me know if it helps you. I would appreciate feedback on it. – milancurcic Jun 28 '13 at 15:54

3 Answers3

6

I often work with dates and times in Fortran, so I ended up writing a library for it:

http://github.com/milancurcic/datetime-fortran

It supports basic arithmetic and comparison operators for datetime and timedelta objects (loosely modeled after Python's datetime), and also provides interfaces to C strftime and strptime, and more.

Since version 0.3.0, strftime and strptime interfaces are defined to operate directly on datetime instances, so there is no need to fiddle with tm_structs.

Here is a simple program that will handle your case:

USE datetime_module

TYPE(datetime)  :: date1,date2
TYPE(timedelta) :: timediff

CHARACTER(LEN=15) :: str1 = "20130512 091519"
CHARACTER(LEN=15) :: str2 = "20131116 120418"

date1 = strptime(str1,"%Y%m%d %H%M%S")
date2 = strptime(str2,"%Y%m%d %H%M%S")

timediff = date2-date1

WRITE(*,*)timediff
WRITE(*,*)timediff % total_seconds()

END

Outputs:

     188           2          48          59           0
  16253339.000000000 

on my computer.

milancurcic
  • 6,202
  • 2
  • 34
  • 47
  • Your package seems quite sophisticated, its just that it has over 2000 lines of code and I am already struggling to grasp cups one liner without actual coding in it. I'm gonna continue calculations with the results I get out as time differences, so in case of errors within the output I imagine it painfull to check the time calculations as well as my routines on top of it. I as a fortran beginner am way busy enough with the stuff that is supposed to work on top of it... But I'm sure it was great for my task if I had a bit more experience on programming fortran. – Stephen Rewitz Jun 28 '13 at 20:34
  • So none the less: appreciated a lot! – Stephen Rewitz Jun 28 '13 at 20:41
  • You are just supposed to call that code according to IRO-bot's example, it should be quite simple. At least simpler than inventing your own solution. Number of lines in a called library is completely irrelevant, you do not have to understand it all. – Vladimir F Героям слава Jun 29 '13 at 07:30
  • How to use your package `datetime-fortran` with `mingw`, where the `strptime` function is missing on windows? – sunt05 May 31 '18 at 20:42
  • @sunt05 No clue -- I have zero experience with mingw. I assume that installing gcc in mingw would make its standard library available (look for time.h header file). – milancurcic May 31 '18 at 21:01
  • unfortunately, `strptime` is not included in the `gcc` bundle shipped with `mingw`. There are some workarounds here: https://stackoverflow.com/questions/321849/strptime-equivalent-on-windows?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa, but I couldn't get the compilation done with your package. You are much appreciated if any suggestion/help! I really like your package and don't want to replace it with other implementations. – sunt05 May 31 '18 at 21:07
2

If you always follow the rules of YYYYMMDD HHMMSS, it can be parsed with the format

I4,2I2,1X,3I2

Working out the seconds from HHMMSS is easy. HH*3600 + MM*60 + SS. Working out the seconds from YYYYMMDD is not so easy. You need something like a variant of Zeller's congruence. In C, this would be

DD + ((MM >= 3? (MM + 1): (MM + 13))*30.6001) + ((MM>=3?YYYY:(YYYY-1)) * 1461 / 4)

This variant works from 1900 to Feb28 2100. After that it is out by 1 day. The number you will get is very large so pick a starting point like 20000101 and subtract that value. Multiply that figure by 86400, add the HHMMSS computation and you will get the number of seconds since 01/01/2000.

The original formula uses 30.6 but you'll need the extra 001 for 32-bit reals because the 6 times table doesn't translate very well when shifted by one decimal place.

cup
  • 7,589
  • 4
  • 19
  • 42
  • Since there seem no fortran intern solutions in sight so far, I think I'm going to try it with this approach. Your one liner seems to be to the point and still very basic. The valid range (1900 to 2100) is easily sufficient, but I have trouble understanding what this line does, wikipedias 'zellner congruence' couldn't light me up either, sorry. Would be very helpful for me if you could explain what the single parts do or how they work together. And you said "in C", what has to be done different for fortran? – Stephen Rewitz Jun 28 '13 at 20:28
  • The line uses the ternary operator `?`; it is basically an in-line `if` statement: `if (MM >= 3) then (MM-2) else (MM+10)`. In Fortran, you would use `merge`: `time = DD + MERGE(MM-2, MM+10, MM >= 3)`. That is , MERGE(true, false, logical operation). – Kyle Kanos Jun 29 '13 at 02:13
  • @Stephen: I've changed the formula. The old variant works for days of the week but not for date ranges. The modified one works for date ranges.@Kyle: thanks for that. – cup Jun 29 '13 at 05:13
  • @cup: no problem. I discovered `MERGE` a few months back and have been using (abusing?) it since. – Kyle Kanos Jun 30 '13 at 01:30
0

I was looking for some logic about date in fortran. I found something that is compact and could help you too!!

      INTEGER FUNCTION JD (YEAR,MONTH,DAY)
C
C---COMPUTES THE JULIAN DATE (JD) GIVEN A GREGORIAN CALENDAR
C   DATE (YEAR,MONTH,DAY).
C
      INTEGER YEAR,MONTH,DAY,I,J,K
C
      I= YEAR
      J= MONTH
      K= DAY
C
      JD= K-32075+1461*(I+4800+(J-14)/12)/4+367*(J-2-(J-14)/12*12)
     &    /12-3*((I+4900+(J-14)/12)/100)/4
C
      RETURN
      END

more info at: http://aa.usno.navy.mil/faq/docs/JD_Formula.php

  • 1
    What is this doing? Can you please explain more than 'here is some code and a link'. – Ross Jul 10 '18 at 13:59
  • Hi sure, is "translating" georgian time to julian time, julian time is ordering the days as integer, so to do a difference between two times is just about translate them from gegorian to julian calendar and then do the difference of the two integers. if you need to go down to the minutes or seconds is just a matter of multiplications. the julian calendar is a standard calendar used for those porpouses, it simpify all mess related to different lengths of months and bissextile years. – Matteo Mana Jul 10 '18 at 15:24
  • I'm looking for the same thing, but in reverse. ie. given an INTEGER date (in days), return YYYYMMDD. Do you have code for that? – Adrian Apr 16 '21 at 18:47
  • I'm sorry I didn't had the need of it. – Matteo Mana Apr 19 '21 at 12:36