purebasic.info

PureBasic forum
Текущее время: Пн фев 18, 2019 3:16 am

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: Получить разницу в датах
СообщениеДобавлено: Вс фев 03, 2019 10:12 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 333
Благодарил (а): 28 раз.
Поблагодарили: 40 раз.
Пункты репутации: 0
Как обычно конвертировал очередную свою функцию AutoIt3 в процедуру PureBasic и возможно там ещё куча ошибок, просто я не могу продвинутся дальше 28 строки Select Old(1), которая выдаёт ошибку "Строка 28: Число размерности должно быть не менее 1 для: Old().". Я вроде создал массив на 6 элементов, причём здесь не менее 1?
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
ImportC "msvcrt.lib"
        swprintf(*s, Format.s, Param1=0, Param2=0, Param3=0, Param4=0, Param5=0, Param6=0)
EndImport
Error_Procedure = 0
 
; AutoIt3 UDF
Procedure _DateIsLeapYear(Year)
        If Mod(Year, 4) = 0 And Mod(Year, 100) <> 0
                ProcedureReturn 1
        ElseIf Mod(Year, 400) = 0
                ProcedureReturn 1
        Else
                ProcedureReturn 0
        EndIf
EndProcedure
 
; @AZJIO
Procedure __DateDiff_2(Array Old(1), Array New(1), Array R(1))
        Protected i, t = 0, Dim L(5)
        L(0) = 5 ; не используется, размер массива
        L(1) = 12; месяцев в годе
        L(2) = 0 ; дней в месяце, определяется по условию
        L(3) = 24; часов в дне
        L(4) = 60; минут в часе
        L(5) = 60; секунд в минуте
        For i = 5 To 1 Step -1
                If i = 2
                        Select Old(1)
                                Case 1, 3, 5, 7, 8, 10, 12 ; месяца в которых 31 день
                                        L(i) = 31
                                Case 2
                                        If _DateIsLeapYear(Old(0)) ; если високосный год, то в феврале:
                                                L(i) = 29
                                        Else
                                                L(i) = 28
                                        EndIf
                                Default ; в остальных 30 дней
                                        L(i) = 30
                        EndSelect
                EndIf
                ; тут метод вычитания с заёмом
                If (New(i) - t) < Old(i)
                        R(i) = New(i) + L(i) - t - Old(i)
                        t = 1
                Else
                        R(i) = New(i) - t - Old(i)
                        t = 0
                EndIf
        Next
        R(0) = New(0) - Old(0) - t ; отдельно для годов
        ProcedureReturn
EndProcedure
 
; @AZJIO
Procedure.s DateDiff_2(Array Old(1), Array New(1))
        If ArraySize(Old()) < 5 ; проверка размера массива
                Error_Procedure = -1
                ProcedureReturn
        EndIf
        If ArraySize(New()) < 5
                Error_Procedure = -2
                ProcedureReturn
        EndIf
        Protected Extended = 0 ; дополнительный параметр, определяет что старая дата больше новой
        Protected Dim R(6)         ; массив для результата
        R(0) = 0
        R(1) = 0
        R(2) = 0
        R(3) = 0
        R(4) = 0
        R(5) = 0
        ;       Цикл определяет какая дата больше или новее
        For i = 0 To 5
                If Old(i) <> New(i) ; если элементы не равны, то только тогда можно выявить старшинство, иначе переходим к младшему разряду - следующий шаг цикла
                        If Old(i) < New(i) ; еслпи старая меньше (как и должно быть), то вызываем в первом параметре старый
                                __DateDiff_2(Old(), New(), R())
                        Else ; иначе вызываем новый как старый в первом параметре
                                __DateDiff_2(New(), Old(), R())
                                Extended = 1
                        EndIf
                        Break
                EndIf
        Next
       
        ;       Можно было бы переделать на возврат массива (по ссылке), но делаем строкой
        Protected Buff.s{100}
        swprintf(@Buff, "%d.%02d.%02d %02d:%02d:%02d", R(0), R(1), R(2), R(3), R(4), R(5))
        If Extended
                Buff = "-" + Buff
        EndIf
        ProcedureReturn Buff
EndProcedure
 
 
Dim date1(5)
date1(0) = 1922
date1(1) = 5
date1(2) = 31
date1(3) = 8
date1(4) = 40
date1(5) = 3
 
Dim date2(5)
date2(0) = 1934
date2(1) = 9
date2(2) = 25
date2(3) = 12
date2(4) = 56
date2(5) = 17
; не обязательно указывать дату, можно указать только время, тогда получим разницу только времени.
Debug DateDiff_2(date1(), date2()) ; 12.03.24 04:16:14



Заработало, но я вместо Array Old(6), Array New(6) указал Array Old(1), Array New(1)..... однако. То есть (1) это размерность а не число элементов в массиве? То есть при New(2) элементы бы обозначались New(1, 1) и т.д.?


Последний раз редактировалось AZJIO Вт фев 05, 2019 1:04 am, всего редактировалось 4 раз(а).

Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 2:20 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Чт июн 25, 2009 1:02 pm
Сообщений: 2311
Откуда: Russia — Belarus
Благодарил (а): 7 раз.
Поблагодарили: 73 раз.
Пункты репутации: 11
Что за кошмар. В PB же UnixTime. Отнимаешь как число и всё.

_________________
EnableExplicit User


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 5:42 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 165
Откуда: Україна
Благодарил (а): 12 раз.
Поблагодарили: 13 раз.
Пункты репутации: 9
qpAHToMAS, а как быть с датами до эпохи Unix?

Код:
1
debug Date(1934, 9, 25, 12, 56,17)



Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 6:24 pm 
Не в сети
МОДЕРАТОР

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6473
Благодарил (а): 27 раз.
Поблагодарили: 210 раз.
Пункты репутации: 57
LinXP писал(а):
qpAHToMAS, а как быть с датами до эпохи Unix?

Код:
1
debug Date(1934, 9, 25, 12, 56,17)


Проблема есть. Но решать её при помощи массивов как то дико.
Есть же структура, типа такой
sTime.SYSTEMTIME
sTime\wYear = year
sTime\wMonth = month
sTime\wDay = day
sTime\wHour = hour
sTime\wMinute = minute
sTime\wSecond = second

отсюда и надо плясать.

_________________
read-only ¯\_(ツ)_/¯


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 7:43 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 747
Благодарил (а): 2 раз.
Поблагодарили: 37 раз.
Пункты репутации: 9
Что то не фурычит. :roll:
PS:Да и в месяцах и годах на сколько точное прошедшее время.в днях нужно
например 25,9,1934 был вторник :D
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 
ImportC "msvcrt.lib"
        swprintf(*s, Format.s, Param1=0, Param2=0, Param3=0, Param4=0, Param5=0, Param6=0)
EndImport
Error_Procedure = 0
 
; AutoIt3 UDF
Procedure _DateIsLeapYear(Year)
        If Mod(Year, 4) = 0 And Mod(Year, 100) <> 0
                ProcedureReturn 1
        ElseIf Mod(Year, 400) = 0
                ProcedureReturn 1
        Else
                ProcedureReturn 0
        EndIf
EndProcedure
 
; @AZJIO
Procedure __DateDiff_2(Array Old(1), Array New(1))
        Protected i, t = 0, Dim L(5)
        L(0) = 5
        L(1) = 12
        L(2) = 0
        L(3) = 24
        L(4) = 60
        L(5) = 60
        For i = 5 To 1 Step -1
                If i = 2
                        Select Old(1)
                                Case 1, 3, 5, 7, 8, 10, 12
                                        L(i) = 31
                                Case 2
                                        If _DateIsLeapYear(Old(0))
                                                L(i) = 29
                                        Else
                                                L(i) = 28
                                        EndIf
                                Default
                                        L(i) = 30
                        EndSelect
                EndIf
                If New(i) - t < Old(i)
                        t = 1
                        Old(i) = New(i) + L(i) - t - Old(i)
                Else
                        Old(i) = New(i) - t - Old(i)
                        t = 0
                EndIf
        Next
 
        Old(0) = New(0) - Old(0) - t
        ProcedureReturn
EndProcedure
 
; @AZJIO
Procedure.s DateDiff_2(Array Old(1), Array New(1))
;       If ArraySize(Old()) < 5
;               Error_Procedure = -1
;               ProcedureReturn
;       EndIf
;       If ArraySize(New()) < 5
;               Error_Procedure = -2
;               ProcedureReturn
;       EndIf
        Protected Extended = 0
        Protected d=1
        ;       Protected Dim d(6)
        ;               d(0) = 0
        ;               d(1) = 0
        ;               d(2) = 0
        ;               d(3) = 0
        ;               d(4) = 0
        ;               d(5) = 0
        For i = 0 To 5
                If Old(i) <> New(i)
                        If Old(i) < New(i)
                                __DateDiff_2(Old(), New())
                                d = 0
                        Else
                                __DateDiff_2(New(), Old())
                                d = 0
                                Extended = 1
                        EndIf
                        Break
                EndIf
        Next
        If d
                Old(0) = 0
                Old(1) = 0
                Old(2) = 0
                Old(3) = 0
                Old(4) = 0
                Old(5) = 0
        EndIf
 
        ;       If iArray
        ;               ProcedureReturn SetError(0, Extended, d)
        ;       Else
        ;               ProcedureReturn Extended
        Protected Buff.s{100}
        swprintf(@Buff, "%d.%02d.%02d %02d:%02d:%02d", Old(0), Old(1), Old(2), Old(3), Old(4), Old(5))
        ;               Debug Buff
        If Extended
                Buff = "-" + Buff
        EndIf
        ProcedureReturn Buff
        ;       EndIf
EndProcedure
 
Dim date1(5)
date1(0) = 1922
date1(1) = 1
date1(2) = 1
date1(3) = 8
date1(4) = 40
date1(5) = 3
 
Dim date2(5)
date2(0) = 1922
date2(1) = 12
date2(2) = 28
date2(3) = 12
date2(4) = 56
date2(5) = 17
Debug DateDiff_2(date1(), date2()) ;361 день
 
 



Последний раз редактировалось Сергейчик Пн фев 04, 2019 8:04 pm, всего редактировалось 2 раз(а).

Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 7:56 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 333
Благодарил (а): 28 раз.
Поблагодарили: 40 раз.
Пункты репутации: 0
qpAHToMAS писал(а):
Что за кошмар. В PB же UnixTime. Отнимаешь как число и всё.
и что получаем? миллион миллисекунд до твоего дня рождения? как это воспринять мозгом промежуток? Опять же если перевести это в года или в месяцы опять неудобство восприятия, но даже если разделить на число целых годов, целых месяцев и т.д., то как определяем длину года в високосных или в обычных? А месяцы как 28, 29, 30, 31? И если будем рассчитывать учитывая какой год, месяц, то придём к той же функции. Кстати, в AutoIt3 также есть все эти функции и я о них конечно же знаю (сам половину перевёл на русский), поэтому к своей функции добавил индекс _2.

kvitaliy писал(а):
Но решать её при помощи массивов как то дико..
Почему дико? В структуре удобство имён только и всего. А как быть если надо в цикле обрабатывать? Да и главное решение, а кто как будет хранить в чём данные не важно.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 8:02 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 333
Благодарил (а): 28 раз.
Поблагодарили: 40 раз.
Пункты репутации: 0
Сергейчик писал(а):
в днях нужно
часы минуты секунды не указывай, оставь по нулям, будет в днях... ну не без месяцев конечно, если нужно только в днях используй стандартные функции, миллисекунды дели на число сколько миллисекунд в дне.
_______________________
Я на отрицательность ещё не проверял вчера, сейчас проверил, пока выдаёт не то. Буду ещё исправлять.


Последний раз редактировалось AZJIO Пн фев 04, 2019 8:07 pm, всего редактировалось 1 раз.

Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 8:07 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 747
Благодарил (а): 2 раз.
Поблагодарили: 37 раз.
Пункты репутации: 9
AZJIO писал(а):
Сергейчик писал(а):
в днях нужно
часы минуты секунды не указывай, оставь по нулям, будет в днях... ну не без месяцев конечно, если нужно только в днях используй стандартные функции, миллисекунды дели на число сколько миллисекунд в дне.

В дне их столько что пожалуй эти данные размерностью между дней не влезут даже в тип q. :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 8:09 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 333
Благодарил (а): 28 раз.
Поблагодарили: 40 раз.
Пункты репутации: 0
Сергейчик писал(а):
В дне их столько что пожалуй эти данные не влезут даже в тип q.
в с плавающей точкой влезут? С мантиссой и экспонентой...

Разгадал проблему. У меня возврат делается в массив в первом параметре, и в первом случае Old и его я использовал как результат, а во втором он же возвращается в New. Придётся копировать массив. И кстати они портятся на выходе так как передаются по ссылке. В варианте AutoIt3 я возвращал в новый массив, похоже придётся создать временный и передать результаты в него, не портя исходные по ссылке.

Исправил в первом посте!!! С комментариями в коде.

Сергейчик писал(а):
нужно
например 25,9,1934 был вторник
так это другая функция, определения дня недели по дате


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Пн фев 04, 2019 10:42 pm 
Не в сети
доцент
Аватар пользователя

Зарегистрирован: Вт мар 03, 2015 4:20 pm
Сообщений: 26
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Structure TimeDiff 
  totaldays.l
  years.l
  months.l
  daysremaining.l
  hours.l
  minutes.l
  seconds.l
EndStructure
 
Procedure.s DateDiff(hStartDate, hEndDate, *diff.TimeDiff)
 
  Protected totaldays,years,months,daysremaining,hours,minutes,seconds
 
  curdate = hStartDate
  testdate = hStartDate
  startday = Day(hStartDate)
  totaldays = 0
  daysremaining = 0
 
  While testdate <= hEndDate
    testdate = AddDate(curdate, #PB_Date_Day, 1)
    If testdate <= hEndDate
      curdate = testdate
      totaldays+1
      daysremaining+1
      If Day(curdate) = startday
        months+1
        daysremaining=0
      EndIf
    EndIf
  Wend
 
  testdate = curdate
  hours = 0
  While testdate<hEndDate
    testdate = AddDate(curdate, #PB_Date_Hour, 1)
    If testdate <= hEndDate
      curdate = testdate
      hours+1
    EndIf
  Wend
 
  testdate = curdate
  minutes = 0
  While testdate<hEndDate
    testdate = AddDate(curdate, #PB_Date_Minute, 1)
    If testdate <= hEndDate
      curdate = testdate
      minutes+1
    EndIf
  Wend
 
  testdate = curdate
  seconds = 0
  While testdate<hEndDate
    testdate = AddDate(curdate, #PB_Date_Second, 1)
    If testdate <= hEndDate
      curdate = testdate
      seconds+1
    EndIf
  Wend
 
  years = months/12
  If years
    months % 12
  EndIf
 
  *diff\totaldays = totaldays
  *diff\years = years
  *diff\months = months
  *diff\daysremaining = daysremaining
  *diff\hours = hours
  *diff\minutes = minutes
  *diff\seconds = seconds
 
;   ProcedureReturn
EndProcedure
 
MyDiff.TimeDiff
 
; hStartDate = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2015/5/12/12:30:00")
; hEndDate = Date()
 
;Example
; DateDiff(hStartDate, hEndDate,@MyDiff)
 
; Debug "Total Days: "+Str(MyDiff\totaldays)
; Debug "Years: "+Str(MyDiff\years)
; Debug "Months: "+Str(MyDiff\months)
; Debug "Days: "+Str(MyDiff\daysremaining)
; Debug "Hours: "+Str(MyDiff\hours)
; Debug "Minutes: "+Str(MyDiff\minutes)
; Debug "Seconds: "+Str(MyDiff\seconds)



Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Получить разницу в датах
СообщениеДобавлено: Вт фев 05, 2019 12:41 am 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 333
Благодарил (а): 28 раз.
Поблагодарили: 40 раз.
Пункты репутации: 0
Deomack
Сравнил результаты с моими, пришёл к выводу что мне нужно переосмыслить метод вычитания столбиком с заёмом. Всё таки нашёл я у себя гарантированно-выявленную ошибку.

Но в вашем примере добавлять по единице в цикле пока дата не совпадёт кажется тоже не идеал. Должен быть метод вычисления, а не метод подбора.

Сделал у себя в коде поправку и снова тестируем
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Dim date1(5)
date1(0) = 2018
date1(1) = 5
date1(2) = 12
date1(3) = 12
date1(4) = 0
date1(5) = 0
 
Dim date2(5)
date2(0) = 2019
date2(1) = 5
date2(2) = 12
date2(3) = 11
date2(4) = 0
date2(5) = 0


аналогично
Код:
1
2
hStartDate = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2018/5/12/12:0:0") 
hEndDate = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2019/5/12/11:0:0")


мой возвращает 0.11.30 23:00:00
ваш
Цитата:
Total Days: 364
Years: 0
Months: 11
Days: 29
Hours: 23
Minutes: 0
Seconds: 0

Разница в год минус 1 час должен дать все на единицу меньше 11 месяцев (против 12), 30 дней (против 31), 23 часа (против 24 часов). Но у вас возвращает 29 дней. Мы ведь берём дни до конца мая в котором 31 день, потом 11 месяцев и снова дни начала мая, в общем май без часа равно 31 день без часа. Проверил поставил 4-й месяц, теперь ваша функция дала 30 дней, а моя 29, должно быть 29.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Bing [Bot] и гости: 12


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB