Private Sub GetStrTo(strFrom As String) As String
Try
Dim TimeFormatShow As String="hh:mm a",DateFormat As String="MM/dd/yyyy"
DateTime.TimeFormat=TimeFormatShow
DateTime.DateFormat=DateFormat
Dim Arr() As String
Dim NotTimeDate As String,NoteTimeStr As String
Dim P As Period
Dim Tick As Long ,NewTick As Long
Dim strTo As String
Dim AddHour As Int
Arr=Regex.Split(" ", strFrom)
NotTimeDate=Arr(0)
NoteTimeStr=Arr(1) & " " & Arr(2)
Tick=DateTime.DateTimeParse(NotTimeDate,NoteTimeStr)
AddHour=1
P.Hours=AddHour
NewTick=DateUtils.AddPeriod(Tick,P)
strTo=DateUtils.TicksToString(NewTick)
Return strTo
Catch
Log("GetStrTo " & LastException.Message)
Return "Error"
End Try
End Sub
On DST day I have this problem.
My question is - how to add 1 hour to 03/13/2022 1:00 AM to get 03/13/2022 2:00 AM but not 3:00 AM?
Thanks for your idea but I need to show this time stamp to the user and if I convert it back to local time EST DTS - guess what?Assuming that you need to use the DateTime math to handle when adding hours crosses end-of-month boundaries, then the simplest solution might be to (temporarily) treat your notes' timestamps as being UTC rather than being the local timezone.
Thanks for your idea but I need to show this time stamp to the user and if I convert it back to local time EST DTS - guess what?
treat your note timestamp yyyy-mm-dd-hh-mm-ss as being UTC
I created a sub that determines if the date the second Sunday of March of any year, it bypasses the DST, since in America DST happens the 2nd Sunday of March of every year . See if the attached project fits in with what you are thinking. Of course, it can be tweaked.I need to show this time stamp to the user
since in America DST happens the 2nd Sunday of March of every year
My question is - how to add 1 hour to 03/13/2022 1:00 AM to get 03/13/2022 2:00 AM but not 3:00 AM?
My solution - if it's DST and timestr is "01;00 AM"just replace it with "02:00 AM" and if it's "02:00 AM" replace it with "03:00 AM".Is it always 1 hour that you're adding?
Could it cross the midnight wraparound? (and thus potentially the date change from 28th/29th/30th/31st of one month to the 1st of the next) (maybe year too)
What is your plan for the first Sunday in November when the times double-up for an hour? (eg there are two local 1:30 AMs, one hour apart)
And backing away from the trees so that we can see the forest: what is the actual practical reason for doing this? Is it of a large-enough consequence to matter? Like, if it is a school timetable, are there classes actually running at 1am on a Sunday anyway?
On a related note: I used to work nightshift, and we handled my pay by just ignoring the whole issue because (i) it averaged itself out over the year, and (ii) it would cost more time and confusion and potential for error in sorting out than it was worth.
If IsDST="True" And NoteTimeStr="01:00 AM" Then
NoteTimeStr=NoteTimeStr.Replace("01:00 AM","02:00 AM")
Return NotTimeDate & " " & NoteTimeStr
Else If IsDST="True" And NoteTimeStr="02:00 AM" Then
NoteTimeStr=NoteTimeStr.Replace("02:00 AM","03:00 AM")
Return NotTimeDate & " " & NoteTimeStr
End If
public Sub CheckDST(Tick As Long) As String
Try
Dim IsWait As String
Dim IsDST As Boolean
IsDST=DidTimeZoneChange
Dim TickFrom As Long,TickTo As Long
TickFrom=DateTime.DateTimeParse(Today ,"1:00 AM")
TickTo=DateTime.DateTimeParse(Today ,"2:00 AM")
If IsDST=False Then
IsWait="False"
Return IsWait
End If
If Tick>=TickFrom And Tick<=TickTo Then
IsWait="True"
Else
IsWait="False"
End If
Return IsWait
Catch
Log("CheckDST " & LastException.Message)
ShowError("modFun_CheckDST " & LastException.Message)
Return "Error"
End Try
End Sub
Private Sub DidTimeZoneChange () As Boolean
Dim date As Long=DateTime.DateParse(Today)
Dim Start As Long = DateUtils.SetDateAndTime(DateTime.GetYear(date), DateTime.GetMonth(date), DateTime.GetDayOfMonth(date), 0, 0, 0)
Dim EndDate As Long = DateUtils.SetDateAndTime(DateTime.GetYear(date), DateTime.GetMonth(date), DateTime.GetDayOfMonth(date), 23, 0, 0)
Return DateTime.GetTimeZoneOffsetAt(Start) <> DateTime.GetTimeZoneOffsetAt(EndDate)
End Sub
My solution - if it's DST and timestr is "01;00 AM"just replace it with "02:00 AM" and if it's "02:00 AM" replace it with "03:00 AM".
May look dirty but I don't see any other solutions so far...
Yes, even you started at 8:45 PM it will be 9:45 PM, 10:45 PM, 11:45 PM but they shift must end at 12:00 AM and the next one will start at 12:00 AM - it will be done automatically.Are your note timestamps guaranteed to always be hh:00 ? ie never 1:30 or 2:25 etc?
Hey, if it works... ?
Although might be good idea to comment that code well, so that when you're back there in 8 months time, you'll have a fighting chance of success then too.
Waiting for debugger to connect...
Program started.
Hello world!!!
(ArrayList) [3, 13, 2022, 1, 0] 'DST start date 1:00 AM
(ArrayList) [0, 0, 0, 1, 0] 'plus 1 hour (01:00)
(ArrayList) [3, 13, 2022, 2, 0, 0] '= 2:00:00 (AM)
(ArrayList) [3, 13, 2022, 20, 35] '08:35 PM (20:35)
(ArrayList) [0, 0, 0, 10, 47, 16] 'plus 10 hours 47 minutes 16 seconds
(ArrayList) [3, 14, 2022, 7, 22, 16] '= next day 07:22:16 (AM)
Program terminated (StartMessageLoop was not called).
Log("Hello world!!!")
Dim S As String = "03/13/2022 01:00"
Log(DateComponents(S))
Dim I As String = "00/00/0000 01:00"
Log(DateComponents(I))
Log(AddDates(S, I))
Dim S As String = "03/13/2022 20:35"
Log(DateComponents(S))
Dim I As String = "00/00/0000 10:47:16"
Log(DateComponents(I))
Log(AddDates(S, I))
Sub DateComponents(D As String) As List 'returns list of day, month, year and (if sepecified) hour, minute, second
'''Dim ComponentMin() As Int = Array As Int( 1, 1, 1800, 0, 0, 0) 'spewin! date increment components mostly 0
Dim ComponentMin() As Int = Array As Int( 0, 0, 0, 0, 0, 0)
Dim ComponentMax() As Int = Array As Int(12,31, 2222, 59, 59, 60) 'leap second is 60
Dim Components As List
Components.Initialize
Dim StringComponents() As String = Regex.Split("[^0-9]", D.Trim)
Dim BadDateFlag As Boolean = (StringComponents.Length < 3 Or StringComponents.Length > 6)
If BadDateFlag = False Then
For I = 0 To StringComponents.Length - 1
If IsNumber(StringComponents(I)) = False Then
BadDateFlag = True
Exit
Else
Dim Temp As Int = StringComponents(I)
If Temp < ComponentMin(I) Or Temp > ComponentMax(I) Then
BadDateFlag = True
Exit
End If
Components.Add(Temp)
End If
Next
End If
If BadDateFlag Then
Log("Bad date: """ & D & """")
Components.Initialize 'return empty list if bad
End If
Return Components
End Sub
Sub AddDates(StartDate As String, Increment As String) As List
Dim StartDateComponents As List = DateComponents(StartDate)
Dim IncrementComponents As List = DateComponents(Increment)
If StartDateComponents.Size = 0 Or IncrementComponents.Size = 0 Then
Dim EmptyList As List
EmptyList.Initialize
Return EmptyList 'return empty list if bad
End If
Do While StartDateComponents.Size < 6
StartDateComponents.Add(0)
Loop
Do While IncrementComponents.Size < 6
IncrementComponents.Add(0)
Loop
Dim Sum As Int = 0
Dim Carry As Int = 0
Sum = StartDateComponents.Get(5) + IncrementComponents.Get(5) 'seconds
Carry = 0
Do While Sum >= 60
Sum = Sum - 60
Carry = Carry + 1
Loop
Dim Second As Int = Sum
Sum = StartDateComponents.Get(4) + IncrementComponents.Get(4) + Carry 'minutes
Carry = 0
Do While Sum >= 60
Sum = Sum - 60
Carry = Carry + 1
Loop
Dim Minute As Int = Sum
Sum = StartDateComponents.Get(3) + IncrementComponents.Get(3) + Carry 'hours
Carry = 0
Do While Sum >= 24
Sum = Sum - 24
Carry = Carry + 1
Loop
Dim Hour As Int = Sum
Dim DaysInMonth As Int = 31
Select StartDateComponents.Get(0) 'month
Case 9, 4, 6, 11:
DaysInMonth = 30
Case 2:
If (StartDateComponents.Get(2) Mod 400) = 0 Then 'year
DaysInMonth = 29
else if (StartDateComponents.Get(2) Mod 100) = 0 Then
DaysInMonth = 28
else if (StartDateComponents.Get(2) Mod 4) = 0 Then
DaysInMonth = 29
Else
DaysInMonth = 28
End If
End Select
Sum = StartDateComponents.Get(1) + IncrementComponents.Get(1) + Carry 'days
Carry = 0
If Sum > DaysInMonth Then
Sum = Sum - DaysInMonth
Carry = Carry + 1
End If
Dim Day As Int = Sum
Sum = StartDateComponents.Get(0) + IncrementComponents.Get(0) + Carry 'months
Carry = 0
Do While Sum > 12
Sum = Sum - 12
Carry = Carry + 1
Loop
Dim Month As Int = Sum
Dim Year As Int = StartDateComponents.Get(2) + IncrementComponents.Get(2) + Carry 'years
Dim ReturnValue As List
ReturnValue.Initialize
ReturnValue.Add(Month)
ReturnValue.Add(Day)
ReturnValue.Add(Year)
ReturnValue.Add(Hour)
ReturnValue.Add(Minute)
ReturnValue.Add(Second)
Return ReturnValue
End Sub
This is exactly what I needAlex, I was too far down the rabbit hole to turn around ? on the bright side, this code is coming up with the answer your users are expecting ? :
Log Output with annotations:Waiting for debugger to connect... Program started. Hello world!!! (ArrayList) [3, 13, 2022, 1, 0] 'DST start date 1:00 AM (ArrayList) [0, 0, 0, 1, 0] 'plus 1 hour (01:00)' (ArrayList) [3, 13, 2022, 2, 0, 0] '= 2:00:00 AM (ArrayList) [3, 13, 2022, 20, 35] '08:35 PM (20:35)' (ArrayList) [0, 0, 0, 10, 47, 16] 'plus 10 hours 47 minutes 16 seconds' (ArrayList) [3, 14, 2022, 7, 22, 16] '= next day 07:22:16' Program terminated (StartMessageLoop was not called).
B4X:Log("Hello world!!!") Dim S As String = "03/13/2022 01:00" Log(DateComponents(S)) Dim I As String = "00/00/0000 01:00" Log(DateComponents(I)) Log(AddDates(S, I)) Dim S As String = "03/13/2022 20:35" Log(DateComponents(S)) Dim I As String = "00/00/0000 10:47:16" Log(DateComponents(I)) Log(AddDates(S, I)) Sub DateComponents(D As String) As List 'returns list of day, month, year and (if sepecified) hour, minute, second '''Dim ComponentMin() As Int = Array As Int( 1, 1, 1800, 0, 0, 0) 'spewin! date increment components mostly 0 Dim ComponentMin() As Int = Array As Int( 0, 0, 0, 0, 0, 0) Dim ComponentMax() As Int = Array As Int(12,31, 2222, 59, 59, 60) 'leap second is 60 Dim Components As List Components.Initialize Dim StringComponents() As String = Regex.Split("[^0-9]", D.Trim) Dim BadDateFlag As Boolean = (StringComponents.Length < 3 Or StringComponents.Length > 6) If BadDateFlag = False Then For I = 0 To StringComponents.Length - 1 If IsNumber(StringComponents(I)) = False Then BadDateFlag = True Exit Else Dim Temp As Int = StringComponents(I) If Temp < ComponentMin(I) Or Temp > ComponentMax(I) Then BadDateFlag = True Exit End If Components.Add(Temp) End If Next End If If BadDateFlag Then Log("Bad date: """ & D & """") Components.Initialize 'return empty list if bad End If Return Components End Sub Sub AddDates(StartDate As String, Increment As String) As List Dim StartDateComponents As List = DateComponents(StartDate) Dim IncrementComponents As List = DateComponents(Increment) If StartDateComponents.Size = 0 Or IncrementComponents.Size = 0 Then Dim EmptyList As List EmptyList.Initialize Return EmptyList 'return empty list if bad End If Do While StartDateComponents.Size < 6 StartDateComponents.Add(0) Loop Do While IncrementComponents.Size < 6 IncrementComponents.Add(0) Loop Dim Sum As Int = 0 Dim Carry As Int = 0 Sum = StartDateComponents.Get(5) + IncrementComponents.Get(5) 'seconds Carry = 0 Do While Sum >= 60 Sum = Sum - 60 Carry = Carry + 1 Loop Dim Second As Int = Sum Sum = StartDateComponents.Get(4) + IncrementComponents.Get(4) + Carry 'minutes Carry = 0 Do While Sum >= 60 Sum = Sum - 60 Carry = Carry + 1 Loop Dim Minute As Int = Sum Sum = StartDateComponents.Get(3) + IncrementComponents.Get(3) + Carry 'hours Carry = 0 Do While Sum >= 24 Sum = Sum - 24 Carry = Carry + 1 Loop Dim Hour As Int = Sum Dim DaysInMonth As Int = 31 Select StartDateComponents.Get(0) 'month Case 9, 4, 6, 11: DaysInMonth = 30 Case 2: If (StartDateComponents.Get(2) Mod 400) = 0 Then 'year DaysInMonth = 29 else if (StartDateComponents.Get(2) Mod 100) = 0 Then DaysInMonth = 28 else if (StartDateComponents.Get(2) Mod 4) = 0 Then DaysInMonth = 29 Else DaysInMonth = 28 End If End Select Sum = StartDateComponents.Get(1) + IncrementComponents.Get(1) + Carry 'days Carry = 0 If Sum > DaysInMonth Then Sum = Sum - DaysInMonth Carry = Carry + 1 End If Dim Day As Int = Sum Sum = StartDateComponents.Get(0) + IncrementComponents.Get(0) + Carry 'months Carry = 0 Do While Sum > 12 Sum = Sum - 12 Carry = Carry + 1 Loop Dim Month As Int = Sum Dim Year As Int = StartDateComponents.Get(2) + IncrementComponents.Get(2) + Carry 'years Dim ReturnValue As List ReturnValue.Initialize ReturnValue.Add(Month) ReturnValue.Add(Day) ReturnValue.Add(Year) ReturnValue.Add(Hour) ReturnValue.Add(Minute) ReturnValue.Add(Second) Return ReturnValue End Sub
Yes, even you started at 8:45 PM it will be 9:45 PM, 10:45 PM, 11:45 PM but they shift must end at 12:00 AM and the next one will start at 12:00 AM - it will be done automatically.
When you are printing schedules, a solution that covers both perspectives might be to flag any shifts where the start time and end time have different DST offsets.
This function feels like it might help do that (but I haven't tried it) :
ticks (ms) date time DateTime.GetTimeZoneOffsetAt
============= ======== =========== ==
1664639997806 10/02/22 01:59:57 am 10
1664639998107 10/02/22 01:59:58 am 10
1664639998408 10/02/22 01:59:58 am 10
1664639998709 10/02/22 01:59:58 am 10
1664639999010 10/02/22 01:59:59 am 10
1664639999311 10/02/22 01:59:59 am 10
1664639999612 10/02/22 01:59:59 am 10
1664639999913 10/02/22 01:59:59 am 10
1664640000214 10/02/22 03:00:00 am 11 'skips an hour at 2am on first Sunday in October
1664640000515 10/02/22 03:00:00 am 11
1664640000816 10/02/22 03:00:00 am 11
1664640001117 10/02/22 03:00:01 am 11
1664640001418 10/02/22 03:00:01 am 11
1664640001719 10/02/22 03:00:01 am 11
1664640002020 10/02/22 03:00:02 am 11
1664640002321 10/02/22 03:00:02 am 11
Dim NoteTimestamp As String = "03/13/2022 01:00" 'Alex_197 local daylight saving start
'''Dim NoteTimestamp As String = "10/02/2022 02:00" 'emexes local daylight saving start
DateTime.DateFormat = "MM/dd/yyyy"
DateTime.TimeFormat = "HH:mm"
DateTime.SetTimeZone(0) 'comment out this line to see the original issue (01:00 plus 1 hour = 03:00)
Dim NoteDateTime() As String = Regex.Split("\ ", NoteTimestamp)
'these five lines are not necessary; just making sure things are going to plan
Dim NoteDate As String = NoteDateTime(0)
Dim NoteTime As String = NoteDateTime(1)
Log("NoteTimestamp = """ & NoteTimestamp & """")
Log("Date = """ & NoteDate & """")
Log("Time = """ & NoteTime & """")
Dim ZuluTimestamp As Long = DateTime.DateTimeParse(NoteDateTime(0), NoteDateTime(1))
'these three lines are not necessary; just having a closer look at what the heck we've done
DateTime.DateFormat = "MM/dd/yyyy HH:mm:ss z"
Log(DateTime.Date(ZuluTimestamp))
Log(DateTime.Date(ZuluTimestamp + 60 * 60 * 1000))
DateTime.DateFormat = "MM/dd/yyyy HH:mm"
Log(DateTime.Date(ZuluTimestamp))
Log(DateTime.Date(ZuluTimestamp + 60 * 60 * 1000))
DateTime.DateFormat = DateTime.DeviceDefaultDateFormat
DateTime.TimeFormat = DateTime.DeviceDefaultTimeFormat
'but how to reset timezone???
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?