program generator
implicit none

integer :: year1, month1, day1, hour1, minute1
integer :: year2, month2, day2, hour2, minute2
integer :: dminutes
integer :: year, month, day, hour, minute, sec
character(len=1024) :: argv

logical endflag

sec =0

call get_command_argument(1,  argv)
if( len_trim(argv)  < (4+2+2+2+2) )  then
  write(0,*) 'Wrong Argument ', trim(argv)
  write(0,*) 'ex: ./a.out  201012010000 201101010000 30'
  stop
end if

read( argv, '(I4I2I2I2I2)') year1, month1, day1, hour1, minute1

call get_command_argument(2,  argv)
if( len_trim(argv)  < (4+2+2+2+2) )  then
  write(0,*) 'Wrong Argument ', trim(argv)
  write(0,*) 'ex: ./a.out  201012010000 201101010000 30'
  stop
end if

read( argv, '(I4I2I2I2I2)') year2, month2, day2, hour2, minute2

call get_command_argument(3,  argv)

if( len_trim(argv)  <= 0 )  then
  write(0,*) 'Wrong Argument ', trim(argv)
  write(0,*) 'ex: ./a.out  201012010000 201101010000 30'
  stop
end if

read( argv, *) dminutes

write(0,*) 'start : ',year1, month1, day1, hour1, minute1
write(0,*) 'end   : ',year2, month2, day2, hour2, minute2
write(0,*) 'every ', dminutes

endflag = .FALSE.
year=year1; month=month1; day=day1; hour=hour1; minute=minute1
sec = 0

 write(*, '(I0.4I0.2I0.2I0.2I0.2I0.2)') year, month, day, hour, minute, sec

 do while(endflag  .eqv. .FALSE.)
  call minuteshift( year, month, day, hour, minute, dminutes)
  if( year*10000+month*100+day >  year2*10000+month2*100+day2 ) then
   endflag = .TRUE.
   exit
  end if

  write(*, '(I0.4I0.2I0.2I0.2I0.2I0.2)') year, month, day, hour, minute, sec
 end do

end 

subroutine minuteshift( year, month, day, hour, minute, dminutes)
implicit none
integer :: year, month, day, hour, minute, dminutes
integer :: year_a, month_a, day_a, hour_a
integer :: dh

 minute = minute + dminutes

 if( minute >= 60 ) then
  dh = 0
  do while( minute >= 60 )
  minute = minute - 60
  dh = dh + 1
  end do
  year_a = year; month_a = month; day_a = day; hour_a = hour
  call hourshift( year_a, month_a, day_a, hour_a, dh, year, month, day, hour )
 else if( minute < 0 ) then
  dh = 0
  do while( minute < 0 )
    minute= minute + 60
    dh = dh -1
  end do

  year_a = year; month_a = month; day_a = day; hour_a = hour
  call hourshift( year_a, month_a, day_a, hour_a, dh, year, month, day, hour )
 end if

end


subroutine  hourshift( year1, month1, day1, hour1, shift, year2, month2, day2, hour2 )
implicit none
integer :: year1, month1, day1, hour1, shift, year2, month2, day2, hour2
integer :: addday

  hour2 = hour1 + shift
  if(hour2 >= 24) then
    hour2 = hour2 - 24
    addday = 1
    call  dateadd( year1, month1, day1, addday, year2, month2, day2)
  else if( hour2 < 0 ) then
    hour2 = hour2 + 24
    addday = -1
    call  dateadd( year1, month1, day1, addday, year2, month2, day2)
  else
    day2 = day1
    month2 = month1
    year2 = year1
  end if

return
end

subroutine dateadd( year1, month1, day1, addday, year2, month2, day2)
! add  addday to year1, month1, day1
! results in    year2, month2, day2
  implicit none
  integer :: year1, month1, day1
  integer :: year2, month2, day2
  integer :: addday
  integer :: doy1, doy2, ddd
! functions
  integer :: dayofyear, days_in_year
  logical :: leepyear

  doy1 = dayofyear( year1, month1, day1 )

  doy2 = doy1 + addday
  if( doy2 > 0 )  then
    year2 = year1

    do while( .TRUE. )
      ddd = days_in_year(year2)
      if( doy2 > ddd) then
    	year2 = year2 + 1
	doy2  = doy2 - ddd
      else
        exit
      end if
    end do
   else    ! doy2 <= 0
    year2 = year1 
    do while( doy2 <= 0 )
      year2 = year2 - 1
      ddd = days_in_year(year2)
      doy2 = doy2 + ddd
    end do
   end if

   call doy2monthday( year2, doy2, month2, day2 )
   return

end


subroutine doy2monthday( year, doy, month, day)
! convert year and doy (day of year) into month and day
 implicit none
 integer ::  year, doy, month, day
 integer ::  tmp
! functions
 logical :: leepyear
 integer :: i
 integer :: m(12)
  m(1) = 31; m(2) = 28; m(3) = 31; m(4) = 30
  m(5) = 31; m(6) = 30; m(7) = 31; m(8) = 31
  m(9) = 30; m(10) = 31; m(11) = 30; m(12) = 31

 if( leepyear( year) ) then
  m(2) = 29
 end if

 tmp = 0; month=0
 do while( tmp < doy )
  month = month + 1
  tmp = tmp + m(month)
 end do

 tmp = tmp - m(month)
 day = doy - tmp
end






integer function days_in_year( year )
  implicit none
  integer :: year
  logical :: leepyear

  if( leepyear( year ) ) then
  	days_in_year = 366
  else
  	days_in_year = 365
  end if
end




subroutine datedif( year1a, month1a, day1a, year2a, month2a, day2a, diffday )
!     difference between year1/month1/day1 and year2/month2/day2
!        
  implicit none
  integer :: year1a, month1a, day1a
  integer :: year2a, month2a, day2a
  integer :: year1, month1, day1
  integer :: year2, month2, day2
  integer :: diffday             ! diffday =  (y/m/d)1 - (y/m/d)2
  integer :: dayofyear
  integer :: fact, tmp, tmp2, d1, d2
  logical :: leepyear

	year1 = year1a; month1 = month1a; day1 = day1a
	year2 = year2a; month2 = month2a; day2 = day2a


  if( year1 > year2 ) then
    fact = 1
  else if( year1 <= year2 ) then
    fact = -1
  else 
    if( month1 > month2 ) then
      fact = 1
    else if( month1 <= month2 ) then
      fact = -1
    else
      if( day1 > day2 ) then
        fact = 1
      else if( day1 < day2 ) then
        fact = -1
      else
        fact = 0
      end if
    end if
  end if


  if( fact == 0 ) then
    diffday = 0
    return

  else if( fact == -1 ) then
    tmp = year1; year1 = year2; year2 = tmp
    tmp = month1; month1 = month2; month2 = tmp
    tmp = day1; day1 = day2; day2 = tmp
  end if

 diffday = 0
 
 if( year2 < year1 ) then
  do tmp=year2, year1-1
   if( leepyear(tmp) ) then
    diffday = diffday + 366
   else
    diffday = diffday + 365
   end if
  end do
 end if
  


! count 
! write(*,*) 'year :::', diffday

   d1 = dayofyear( year1, month1, day1 )
   d2 = dayofyear( year2, month2, day2 )
!      write(*,*) year1, month1, day1, d1
!      write(*,*) year2, month2, day2, d2

   diffday = fact*(diffday + d1 - d2)
   return
end



logical function leepyear( year )
 integer :: year

 if( mod(year, 4) > 0 ) then
   leepyear  = .FALSE.
 else if( mod(year, 100) > 0 ) then
   leepyear = .TRUE.
 else if( mod(year, 400) > 0 ) then
   leepyear = .FALSE.
 else
   leepyear = .TRUE.
 end if

return
end

   
integer function dayofyear(year, month, day)
 integer :: year, month, day
 logical :: leepyear
 integer :: i
 integer :: m(12)
  m(1) = 31; m(2) = 28; m(3) = 31; m(4) = 30
  m(5) = 31; m(6) = 30; m(7) = 31; m(8) = 31
  m(9) = 30; m(10) = 31; m(11) = 30; m(12) = 31

 if( leepyear( year) ) then
  m(2) = 29
 end if

 dayofyear = 0

 do i=1, month-1
  dayofyear = dayofyear + m(i)
 end do

 dayofyear = dayofyear + day
 return

end


 






