dccaldatedifference.f90
Go to the documentation of this file.
1 != 日時差の算出.
2 != Evaluate difference of date.
3 !
4 ! Authors:: Yasuhiro MORIKAWA
5 ! Version:: $Id: dccaldatedifference.f90,v 1.7 2010-09-24 07:07:31 morikawa Exp $
6 ! Tag Name:: $Name: $
7 ! Copyright:: Copyright (C) GFD Dennou Club, 2009-. All rights reserved.
8 ! License:: See COPYRIGHT[link:../../COPYRIGHT]
9 !
10 ! このファイルに記載される手続き群は dc_calendar モジュールから提供されます.
11 !
12 ! Procedures described in this file are provided from "dc_calendar" module.
13 !
14 function dccaldatedifference1( start_date, end_date, cal ) result(sec)
15  !
16  ! 日時差を算出します.
17  !
18  ! 省略可能引数 *cal* が省略された場合には, 日時差の算出に
19  ! dc_calendar 内部で保持される暦が用いられます.
20  ! *cal* が省略されない場合にはその変数に設定された暦が用いられます.
21  !
22  ! Evaluate difference of date.
23  !
24  ! If an optional argument *cal* is omitted,
25  ! information of calendar that is stored in the "dc_calendar"
26  ! is used for evaluation of difference of date.
27  ! If *cal* is not omitted, information of the variable is used.
28  !
29 
32  use dc_calendar_types, only: dc_cal, dc_cal_date, &
35  & cal_user_defined, &
38  use dc_message, only: messagenotify
39  use dc_trace, only: beginsub, endsub
40  use dc_types, only: dp, token, string
41  implicit none
42  real(DP):: sec
43  ! *start_date* と *end_date* との差 (秒数).
44  ! Difference (seconds) between *start_date* and *end_date*.
45  type(dc_cal_date), intent(in):: start_date
46  ! 起点となる日時.
47  ! Date of origin.
48  type(dc_cal_date), intent(in):: end_date
49  ! 終点となる日時.
50  ! Date of terminus.
51  type(dc_cal), intent(in), optional, target:: cal
52  ! 暦情報を収めたオブジェクト.
53  !
54  ! An object that stores information of
55  ! calendar.
56 
57  ! 作業変数
58  ! Work variables
59  !
60  type(dc_cal), pointer:: calp =>null()
61  real(DP):: start_year, start_day, start_sec, start_neg_offset_day
62  real(DP):: end_year, end_day, end_sec, end_neg_offset_day
63  integer:: day_in_4years, day_in_400years
64  integer:: start_year_int, end_year_int
65  integer:: i, j
66  character(*), parameter:: subname = 'DCCalDateDifference1'
67 continue
68  ! オブジェクトのポインタ割付
69  ! Associate pointer of an object
70  !
71  if ( present( cal ) ) then
72  calp => cal
73  else
74  calp => default_cal
75  if ( .not. calp % initialized ) call default_cal_set
76  end if
77 
78  ! 初期設定のチェック
79  ! Check initialization
80  !
81  if ( .not. calp % initialized ) then
82  sec = 0.0_dp
83  return
84  end if
85 
86  if ( .not. start_date % initialized ) then
87  sec = 0.0_dp
88  return
89  end if
90 
91  if ( .not. end_date % initialized ) then
92  sec = 0.0_dp
93  return
94  end if
95 
96  start_neg_offset_day = 0
97  end_neg_offset_day = 0
98 
99  start_year_int = start_date % year
100  end_year_int = end_date % year
101 
102  ! 日への変換
103  ! Convert into days
104  !
105  select case( calp % cal_type )
106  case( cal_julian )
107 
108  day_in_4years = 1461
109 
110  ! 年が負の場合,400 年単位で引き算し下駄を履かせる
111  !
112  do while ( start_year_int < 1 )
113  start_neg_offset_day = start_neg_offset_day &
114  & + day_in_4years * 100
115  start_year_int = start_year_int &
116  & + 400
117  end do
118 
119  ! start_date の日への変換
120  ! Convert start_date into days
121  !
122  if ( ( start_year_int - 1 ) > 4 ) then
123  start_day = int( ( start_year_int - 1 ) / 4 ) * day_in_4years
124  start_year = mod( start_year_int - 1, 4 ) + 1
125  else
126  start_day = 0
127  start_year = start_year_int
128  end if
129 
130  start_day = start_day + ( start_year - 1 ) * sum( calp % day_in_month(:) )
131  do i = 1, start_date % month - 1
132  if ( start_year == 4 .and. i == 2 ) then
133  start_day = start_day + 29
134  else
135  start_day = start_day + calp % day_in_month(i)
136  end if
137  end do
138  start_day = start_day + start_date % day
139 
140  ! 年が負の場合,400 年単位で引き算し下駄を履かせる
141  !
142  do while ( end_year_int < 1 )
143  end_neg_offset_day = end_neg_offset_day &
144  & + day_in_4years * 100
145  end_year_int = end_year_int &
146  & + 400
147  end do
148 
149  ! end_date の日への変換
150  ! Convert end_date into days
151  !
152  if ( ( end_year_int - 1 ) > 4 ) then
153  end_day = int( ( end_year_int - 1 ) / 4 ) * day_in_4years
154  end_year = mod( end_year_int - 1, 4 ) + 1
155  else
156  end_day = 0
157  end_year = end_year_int
158  end if
159 
160  end_day = end_day + ( end_year - 1 ) * sum ( calp % day_in_month(:) )
161  do i = 1, end_date % month - 1
162  if ( end_year == 4 .and. i == 2 ) then
163  end_day = end_day + 29
164  else
165  end_day = end_day + calp % day_in_month(i)
166  end if
167  end do
168  end_day = end_day + end_date % day
169 
170  case( cal_gregorian )
171 
172  day_in_400years = 146097
173 
174  ! 年が負の場合,400 年単位で引き算し下駄を履かせる
175  !
176  do while ( start_year_int < 1 )
177  start_neg_offset_day = start_neg_offset_day &
178  & + day_in_400years
179  start_year_int = start_year_int &
180  & + 400
181  end do
182 
183  ! start_date の日への変換
184  ! Convert start_date into days
185  !
186  if ( ( start_year_int - 1 ) > 400 ) then
187  start_day = int( ( start_year_int - 1 ) / 400 ) * day_in_400years
188  start_year = mod( start_year_int - 1, 400 ) + 1
189  else
190  start_day = 0
191  start_year = start_year_int
192  end if
193 
194  do j = 1, int( start_year - 1 )
195  do i = 1, calp % month_in_year
196  if ( i == 2 ) then
197  if ( mod( j, 400 ) == 0 ) then
198  start_day = start_day + 29
199  elseif ( mod( j, 100 ) == 0 ) then
200  start_day = start_day + 28
201  elseif ( mod( j, 4 ) == 0 ) then
202  start_day = start_day + 29
203  else
204  start_day = start_day + 28
205  end if
206  else
207  start_day = start_day + calp % day_in_month(i)
208  end if
209  end do
210  end do
211 
212  do i = 1, start_date % month - 1
213  if ( i == 2 ) then
214  if ( mod( start_year, 400.0_dp ) == 0 ) then
215  start_day = start_day + 29
216  elseif ( mod( start_year, 100.0_dp ) == 0 ) then
217  start_day = start_day + 28
218  elseif ( mod( start_year, 4.0_dp ) == 0 ) then
219  start_day = start_day + 29
220  else
221  start_day = start_day + 28
222  end if
223  else
224  start_day = start_day + calp % day_in_month(i)
225  end if
226  end do
227 
228  start_day = start_day + start_date % day
229 
230  ! 年が負の場合,400 年単位で引き算し下駄を履かせる
231  !
232  do while ( end_year_int < 1 )
233  end_neg_offset_day = end_neg_offset_day &
234  & + day_in_400years
235  end_year_int = end_year_int &
236  & + 400
237  end do
238 
239  ! end_date の日への変換
240  ! Convert end_date into days
241  !
242  if ( ( end_year_int - 1 ) > 400 ) then
243  end_day = int( ( end_year_int - 1 ) / 400 ) * day_in_400years
244  end_year = mod( end_year_int - 1, 400 ) + 1
245  else
246  end_day = 0
247  end_year = end_year_int
248  end if
249 
250  do j = 1, int( end_year - 1 )
251  do i = 1, calp % month_in_year
252  if ( i == 2 ) then
253  if ( mod( j, 400 ) == 0 ) then
254  end_day = end_day + 29
255  elseif ( mod( j, 100 ) == 0 ) then
256  end_day = end_day + 28
257  elseif ( mod( j, 4 ) == 0 ) then
258  end_day = end_day + 29
259  else
260  end_day = end_day + 28
261  end if
262  else
263  end_day = end_day + calp % day_in_month(i)
264  end if
265  end do
266  end do
267 
268  do i = 1, end_date % month - 1
269  if ( i == 2 ) then
270  if ( mod( end_year, 400.0_dp ) == 0 ) then
271  end_day = end_day + 29
272  elseif ( mod( end_year, 100.0_dp ) == 0 ) then
273  end_day = end_day + 28
274  elseif ( mod( end_year, 4.0_dp ) == 0 ) then
275  end_day = end_day + 29
276  else
277  end_day = end_day + 28
278  end if
279  else
280  end_day = end_day + calp % day_in_month(i)
281  end if
282  end do
283 
284  end_day = end_day + end_date % day
285 
286  case default
287  ! start_date の日への変換
288  ! Convert start_date into days
289  !
290  start_day = ( start_year_int - 1 ) * sum( calp % day_in_month(:) )
291  do i = 1, start_date % month - 1
292  start_day = start_day + calp % day_in_month(i)
293  end do
294  start_day = start_day + start_date % day
295 
296  ! end_date の日への変換
297  ! Convert end_date into days
298  !
299  end_day = ( end_year_int - 1 ) * sum ( calp % day_in_month(:) )
300  do i = 1, end_date % month - 1
301  end_day = end_day + calp % day_in_month(i)
302  end do
303  end_day = end_day + end_date % day
304  end select
305 
306  ! start_date の秒への変換
307  ! Convert start_date into seconds
308  !
309  start_sec = ( start_day - 1 - start_neg_offset_day ) &
310  & * calp % hour_in_day &
311  & * calp % min_in_hour &
312  & * calp % sec_in_min &
313  & + start_date % hour * calp % min_in_hour &
314  & * calp % sec_in_min &
315  & + start_date % min * calp % sec_in_min &
316  & + start_date % sec
317 
318  ! end_date の秒への変換
319  ! Convert end_date into seconds
320  !
321  end_sec = ( end_day - 1 - end_neg_offset_day ) &
322  & * calp % hour_in_day &
323  & * calp % min_in_hour &
324  & * calp % sec_in_min &
325  & + end_date % hour * calp % min_in_hour &
326  & * calp % sec_in_min &
327  & + end_date % min * calp % sec_in_min &
328  & + end_date % sec
329 
330  ! 差分の計算
331  ! Calculate difference
332  !
333  sec = end_sec - start_sec
334 
335  ! 終了処理, 例外処理
336  ! Termination and Exception handling
337  !
338 999 continue
339  nullify( calp )
340 end function dccaldatedifference1
341 
342 
343 !!$
344 !!$
345 !!$subroutine DCCalConvertByUnit1( in_time, in_unit, out_unit, out_time, cal, err )
346 !!$ use dc_calendar_internal, only: default_cal, default_cal_set, &
347 !!$ & dccaltype_str, dccaldate_str2usym
348 !!$ use dc_calendar_types, only: DC_CAL, &
349 !!$ & UNIT_SYMBOL_YEAR, UNIT_SYMBOL_MONTH, UNIT_SYMBOL_DAY, &
350 !!$ & UNIT_SYMBOL_HOUR, UNIT_SYMBOL_MIN, UNIT_SYMBOL_SEC
351 !!$ use dc_error, only: StoreError, DC_NOERR, DC_EBADUNIT, DC_ENOTINIT
352 !!$ use dc_message, only: MessageNotify
353 !!$ use dc_trace, only: BeginSub, EndSub
354 !!$ use dc_types, only: DP, TOKEN, STRING
355 !!$ implicit none
356 !!$ real(DP), intent(in):: in_time
357 !!$ character(*), intent(in):: in_unit
358 !!$ character(*), intent(in):: out_unit
359 !!$ real(DP), intent(out):: out_time
360 !!$ type(DC_CAL), intent(in), optional, target:: cal
361 !!$ logical, intent(out), optional:: err
362 !!$ ! 例外処理用フラグ.
363 !!$ ! デフォルトでは, この手続き内でエラーが
364 !!$ ! 生じた場合, プログラムは強制終了します.
365 !!$ ! 引数 *err* が与えられる場合,
366 !!$ ! プログラムは強制終了せず, 代わりに
367 !!$ ! *err* に .true. が代入されます.
368 !!$ !
369 !!$ ! Exception handling flag.
370 !!$ ! By default, when error occur in
371 !!$ ! this procedure, the program aborts.
372 !!$ ! If this *err* argument is given,
373 !!$ ! .true. is substituted to *err* and
374 !!$ ! the program does not abort.
375 !!$
376 !!$ ! 作業変数
377 !!$ ! Work variables
378 !!$ !
379 !!$ type(DC_CAL), pointer:: calp =>null()
380 !!$ real(DP):: in_timew
381 !!$ integer:: in_unit_sym, out_unit_sym
382 !!$ integer:: stat
383 !!$ character(STRING):: cause_c
384 !!$ character(*), parameter:: subname = 'DCCalConvertByUnit1'
385 !!$continue
386 !!$ call BeginSub( subname )
387 !!$ stat = DC_NOERR
388 !!$ cause_c = ''
389 !!$
390 !!$ ! オブジェクトのポインタ割付
391 !!$ ! Associate pointer of an object
392 !!$ !
393 !!$ if ( present( cal ) ) then
394 !!$ calp => cal
395 !!$ else
396 !!$ calp => default_cal
397 !!$ if ( .not. calp % initialized ) call default_cal_set
398 !!$ end if
399 !!$
400 !!$ ! 初期設定のチェック
401 !!$ ! Check initialization
402 !!$ !
403 !!$ if ( .not. calp % initialized ) then
404 !!$ stat = DC_ENOTINIT
405 !!$ cause_c = 'DC_CAL'
406 !!$ goto 999
407 !!$ end if
408 !!$
409 !!$ ! 単位の解釈
410 !!$ ! Parse units
411 !!$ !
412 !!$ in_unit_sym = dccaldate_str2usym( in_unit )
413 !!$ out_unit_sym = dccaldate_str2usym( out_unit )
414 !!$
415 !!$ ! 数値の変換
416 !!$ ! Convert a value
417 !!$ !
418 !!$ select case(in_unit_sym)
419 !!$ case(UNIT_SYMBOL_DAY)
420 !!$ in_timew = in_time * calp % hour_in_day &
421 !!$ & * calp % min_in_hour &
422 !!$ & * calp % sec_in_min
423 !!$ case(UNIT_SYMBOL_HOUR)
424 !!$ in_timew = in_time * calp % min_in_hour &
425 !!$ & * calp % sec_in_min
426 !!$ case(UNIT_SYMBOL_MIN)
427 !!$ in_timew = in_time * calp % sec_in_min
428 !!$ case(UNIT_SYMBOL_SEC)
429 !!$ in_timew = in_time
430 !!$ case default
431 !!$ cause_c = in_unit
432 !!$ call MessageNotify('W', subname, 'in_unit=<%c> is invalid. (ONLY day,hour,min,sec are valid)', &
433 !!$ & c1 = trim(in_unit) )
434 !!$ stat = DC_EBADUNIT
435 !!$ goto 999
436 !!$ end select
437 !!$
438 !!$ select case(out_unit_sym)
439 !!$ case(UNIT_SYMBOL_DAY)
440 !!$ out_time = in_timew / calp % hour_in_day &
441 !!$ & / calp % min_in_hour &
442 !!$ & / calp % sec_in_min
443 !!$ case(UNIT_SYMBOL_HOUR)
444 !!$ out_time = in_timew / calp % min_in_hour &
445 !!$ & / calp % sec_in_min
446 !!$ case(UNIT_SYMBOL_MIN)
447 !!$ out_time = in_timew / calp % sec_in_min
448 !!$ case(UNIT_SYMBOL_SEC)
449 !!$ out_time = in_timew
450 !!$ case default
451 !!$ cause_c = out_unit
452 !!$ call MessageNotify('W', subname, 'out_unit=<%c> is invalid. (ONLY day,hour,min,sec are valid)', &
453 !!$ & c1 = trim(out_unit) )
454 !!$ stat = DC_EBADUNIT
455 !!$ goto 999
456 !!$ end select
457 !!$
458 !!$ ! 終了処理, 例外処理
459 !!$ ! Termination and Exception handling
460 !!$ !
461 !!$999 continue
462 !!$ nullify( calp )
463 !!$ call StoreError( stat, subname, err, cause_c )
464 !!$ call EndSub( subname )
465 !!$end subroutine DCCalConvertByUnit1
integer, parameter, public cal_gregorian
integer, parameter, public unit_symbol_hour
integer, parameter, public cal_julian
integer, parameter, public unit_symbol_month
integer, parameter, public dc_enotinit
Definition: dc_error.f90:557
integer, parameter, public cal_user_defined
integer, parameter, public cal_noleap
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition: dc_types.f90:109
type(dc_cal), target, save, public default_cal
character(token) function, public dccaltype_str(cal_type)
integer, parameter, public unit_symbol_year
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition: dc_error.f90:830
integer, parameter, public dc_noerr
Definition: dc_error.f90:509
integer, parameter, public unit_symbol_day
integer, parameter, public cal_360day
integer, parameter, public dp
倍精度実数型変数
Definition: dc_types.f90:83
subroutine, public beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, version)
Definition: dc_trace.f90:351
real(dp) function dccaldatedifference1(start_date, end_date, cal)
integer, parameter, public dc_ebadunit
Definition: dc_error.f90:559
種別型パラメタを提供します。
Definition: dc_types.f90:49
integer, parameter, public cal_cyclic
integer, parameter, public unit_symbol_min
integer function, public dccaldate_str2usym(str)
subroutine, public default_cal_set
integer, parameter, public unit_symbol_sec
subroutine, public endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
Definition: dc_trace.f90:446
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition: dc_types.f90:118