add hour to field

295 views
Skip to first unread message

paulgilbert2000

unread,
Jul 4, 2021, 4:09:10 PM7/4/21
to TiddlyWiki
Hi ,

I have a filed that in a tiddler that has a date value, i would like to have button to add one hour to the date value , is this possible ?

Eric Shulman

unread,
Jul 4, 2021, 5:57:05 PM7/4/21
to TiddlyWiki
On Sunday, July 4, 2021 at 1:09:10 PM UTC-7 Mohamed...@hotmail.com wrote:
I have a filed that in a tiddler that has a date value, i would like to have button to add one hour to the date value , is this possible ?

By "date value", do you actually mean a full "datetime" value, which in TW is stored as a 17-digit number (YYYYMMDDhhmmssXXX)?  Assuming that is the case, it can be done, but it's not as simple as it may seem.

For instance, if the stored datetime is 20210704133000000 (i.e., 1:30pm on July 4, 2021), then it is relatively easy (though not trivial) to add an hour, like this:
<$button> add an hour
<$vars
   before={{{ [{!!stored_datetime}split[]first[8]join[]] }}}
   hour={{{ [{!!stored_datetime}split[]rest[8]first[2]join[]] }}}
   after={{{ [{!!stored_datetime}split[]rest[10]join[]] }}}>
<$vars newhour={{{ [<hour>add[1]pad[2]] }}}>
<$action-setfield stored_datetime={{{ [<before>addsuffix<newhour>addsuffix<after>] }}} />
</$vars>
</$vars>
</$button>

* First, break the datetime value into parts to isolate the hour number:
** Use split[] to break the datetime value into individual digits, and join the first[8] digits to get the date portion.
** Use rest[8] to get the remaining digits and join the first[2] of those digits to get the hour number.
** Use rest[10] to get the digits following the hour number, and join those to get the minutes, seconds and millisecond portion.
* Next, add 1 to the hour number and apply pad[2] to the result to ensure it is 2 digits with a leading 0 if needed.
* Then, reassemble the parts to give the new datetime value and update the field value.

However... this is not sufficient to handle all possible stored_datetime values.

For example, suppose that the stored datetime is 20210704233000000 (i.e., 11:30pm on July 4, 2021). Simply adding an hour as shown above would give 20210704243000000. But that is not a valid datetime value, as the hours portion must be between 00 and 23.  The correct result would actually be 20210705003000000 (i.e., 12:30am on July 5, 2021).  Thus, we need to handle "hour overflow" to set the hour number to 00 and add 1 to the day number.

But... even that is not enough.  Suppose the stored datetime is 20210731233000000 (i.e., 11:30pm on July 31, 2021). Then adding 1 hour should result in 20210801003000000 (i.e., 12:30am on August 1, 2021). Thus, we not only need to handle "hour overflow" as above, but also "date overflow" to add 1 to the month number.

Complicating this is that the number of days per month varies, so the "date overflow" handling needs to take into account the specified month to know how many days it has.  Further complicating this is leap years, in which the number of days in February is 29 rather than 28, but only for years that are divisible by 4 but not divisible by 100, unless also divisible by 400.

Lastly, we need also to handle "year overflow". If the stored datetime is 20211231233000000 (i.e., 11:30pm on December 31, 2021).  Then adding 1 hour should result in 20220101003000000 (i.e., 12:30am on January 1, 2022).

Obviously, handling all of these issues requires some complex conditional calculations.  Fortunately, I've already tackled this problem in http://tiddlytools.com/timer.html#TiddlyTools%2FTime%2FClocks.  The clock_adjustForTimezone() macro takes the current datetime and adds or subtracts a "timezone offset" value to give a new datetime value.  For your purposes, rather than using the current datetime, you want to get the stored_datetime value, and instead of using a "timezone offset", you want to use a specified offset of 1 hour (i.e., "+01:00")

Here's a modified version of clock_adjustForTimezone() that does what you need:
\define adjust_time()
\whitespace trim
<!-- split time into parts -->
<$vars   yyyy={{{ [<time>split[]first[4]join[]]         }}}>
<$vars     mm={{{ [<time>split[]first[6]last[2]join[]]  }}}>
<$vars     dd={{{ [<time>split[]first[8]last[2]join[]]  }}}>
<$vars     hh={{{ [<time>split[]first[10]last[2]join[]] }}}>
<$vars    min={{{ [<time>split[]first[12]last[2]join[]] }}}>
<$vars  ssxxx={{{ [<time>split[]last[5]join[]]          }}}>
<!-- apply offset "+hh:mm" or "-hh:mm" -->
<$vars   sign={{{ [<offset>split[]first[]]                      }}}>
<$vars  offhh={{{ [<offset>split[]first[3]join[]]               }}}>
<$vars offmin={{{ [<offset>split[]last[2]join[]addprefix<sign>] }}}>
<$vars     hh={{{ [<hh>add<offhh>]   }}}>
<$vars    min={{{ [<min>add<offmin>] }}}>
<!-- adjust days per month for leap year -->
<$set name="leap" value={{{ [<yyyy>remainder[4]match[0]then[yes]] }}}>
<$set name="dpm"  value="31 28 31 30 31 30 31 31 30 31 30 31"> <!-- days per month -->
<$set name="dpm"  filter="[<leap>!match[]]" value="31 29 31 30 31 30 31 31 30 31 30 31" emptyValue=<<dpm>>>
<!-- adjust hours/minutes for minutes wraparound -->
<$set name="hh"   filter="[<min>compare:integer:lt[0]]"    value={{{ [<hh>subtract[1]]      }}} emptyValue=<<hh>>>
<$set name="hh"   filter="[<min>compare:integer:gteq[60]]" value={{{ [<hh>add[1]]           }}} emptyValue=<<hh>>>
<$set name="min"  filter="[<min>compare:integer:lt[0]]"    value={{{ [<min>add[60]]         }}} emptyValue=<<min>>>
<$set name="min"  filter="[<min>compare:integer:gteq[60]]" value={{{ [<min>subtract[60]]    }}} emptyValue=<<min>>>
<!-- adjust date/hours for hours wraparound -->
<$set name="dd"   filter="[<hh>compare:integer:lt[0]]"     value={{{ [<dd>subtract[1]]      }}} emptyValue=<<dd>>>
<$set name="dd"   filter="[<hh>compare:integer:gteq[24]]"  value={{{ [<dd>add[1]]           }}} emptyValue=<<dd>>>
<$set name="hh"   filter="[<hh>compare:integer:lt[0]]"     value={{{ [<hh>add[24]]          }}} emptyValue=<<hh>>>
<$set name="hh"   filter="[<hh>compare:integer:gteq[24]]"  value={{{ [<hh>subtract[24]]     }}} emptyValue=<<hh>>>
<!-- adjust month/date for date wraparound -->
<$set name="dm"   value={{{ [<dpm>split[ ]nth<mm>] }}}> <!-- days in this month -->
<$set name="mm"   filter="[<dd>compare:integer:lteq[0]]"   value={{{ [<mm>subtract[1]]      }}} emptyValue=<<mm>>>
<$set name="mm"   filter="[<dd>compare:integer:gt<dm>]"    value={{{ [<mm>add[1]]           }}} emptyValue=<<mm>>>
<$set name="dd"   filter="[<dd>compare:integer:lteq[0]]"   value={{{ [<dpm>split[ ]nth<mm>] }}} emptyValue=<<dd>>>
<$set name="dd"   filter="[<dd>compare:integer:gt<dm>]"    value={{{ [[1]]                  }}} emptyValue=<<dd>>>
<!-- adjust year/date/month for month wraparound -->
<$set name="yyyy" filter="[<mm>compare:integer:lteq[0]]"   value={{{ [<yyyy>subtract[1]]    }}} emptyValue=<<yyyy>>>
<$set name="yyyy" filter="[<mm>compare:integer:gt[12]]"    value={{{ [<yyyy>add[1]]         }}} emptyValue=<<yyyy>>>
<$set name="dd"   filter="[<mm>compare:integer:lteq[0]]"   value={{{ [[31]]                 }}} emptyValue=<<dd>>>
<$set name="dd"   filter="[<mm>compare:integer:gt[12]]"    value={{{ [[1]]                  }}} emptyValue=<<dd>>>
<$set name="mm"   filter="[<mm>compare:integer:lteq[0]]"   value={{{ [[12]]                 }}} emptyValue=<<mm>>>
<$set name="mm"   filter="[<mm>compare:integer:gt[12]]"    value={{{ [[1]]                  }}} emptyValue=<<mm>>>
<!-- zero-pad and assemble new time -->
<$vars   mm={{{ [<mm>pad[2]] }}} dd={{{ [<dd>pad[2]] }}} hh={{{ [<hh>pad[2]] }}} min={{{ [<min>pad[2]] }}}>
{{{ [<yyyy>addsuffix<mm>addsuffix<dd>addsuffix<hh>addsuffix<min>addsuffix<ssxxx>] }}}
\end

and here's a button that invokes the above to update the stored_datetime field value:

<$button> add an hour
<$vars time={{!!stored_datetime}} offset="+01:00">
<$wikify name="newtime" text=<<adjust_time>>>
<$action-setfield stored_datetime=<<newtime>> />
</$wikify>
</$vars>
</$button>

enjoy,
-e

Brian Radspinner

unread,
Jul 4, 2021, 7:22:07 PM7/4/21
to TiddlyWiki
The compare operator should be added to the Mathematics section of the Filter Operators table, I had no idea it existed until I saw Eric's answer above.

Eric Shulman

unread,
Jul 4, 2021, 7:34:36 PM7/4/21
to TiddlyWiki
<<.group-heading "String Operators">>
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]!tag[Mathematics Operators]tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
<<.group-heading "Mathematics Operators">>
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]tag[Mathematics Operators]!tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>

On Sunday, July 4, 2021 at 4:22:07 PM UTC-7 Brian Radspinner wrote:
The compare operator should be added to the Mathematics section of the Filter Operators table, I had no idea it existed until I saw Eric's answer above.

https://tiddlywiki.com/#compare%20Operator works for both numeric and string comparisons, and is thus tagged as both "Mathematics Operator" and "String Operator".  However, in https://tiddlywiki.com/#Filter%20Operators, each of those tag categories excludes the all other categories, so "compare" does not appear in either table

-e

Soren Bjornstad

unread,
Jul 5, 2021, 9:12:17 AM7/5/21
to TiddlyWiki
Mystery solved! I needed to look up the syntax of compare the other day and thought I was just being dense when I couldn't find it in the list.

paulgilbert2000

unread,
Jul 5, 2021, 2:50:17 PM7/5/21
to TiddlyWiki
Wow  Thanks Eric,

You never respond back with anything less than a full answer , i really wish i could repay you someday for your help and generosity

Thank you sir!

paulgilbert2000

unread,
Jul 11, 2021, 5:07:23 PM7/11/21
to TiddlyWiki
2 more questions

1-can i have this marco work for 2 fields at the same time , so same button pushes an hour for 2 fields

2- can this work for all fields tagged a particular tag , so for example list all tiddlers matching a criteria , then one push of a button adds an hour to all listed tidlers

thanks again

Eric Shulman

unread,
Jul 11, 2021, 10:07:08 PM7/11/21
to TiddlyWiki
On Sunday, July 11, 2021 at 2:07:23 PM UTC-7 Mohamed...@hotmail.com wrote:
1-can i have this macro work for 2 fields at the same time , so same button pushes an hour for 2 fields

Just replicate the code to adjust each field, like this:
<$button> add an hour
<$vars time={{!!field1}} offset="+01:00">
<$wikify name="newtime" text=<<adjust_time>>>
<$action-setfield field1=<<newtime>> />
</$wikify>
</$vars>
<$vars time={{!!field2}} offset="+01:00">
<$wikify name="newtime" text=<<adjust_time>>>
<$action-setfield field2=<<newtime>> />
</$wikify>
</$vars>
</$button>
 
2- can this work for all fields tagged a particular tag , so for example list all tiddlers matching a criteria , then one push of a button adds an hour to all listed tidlers

The code works with a field from the current tiddler, so if you put it within a $list widget that finds all the desired tiddlers, it will update all the tiddlers with one button push:
<$button> add an hour
<$list filter="[tag[sometag]]">
   <$vars time={{!!somefield}} offset="+01:00">
   <$wikify name="newtime" text=<<adjust_time>>>
   <$action-setfield somefield=<<newtime>> />
   </$wikify>
   </$vars>
</$list>
</$button>

enjoy,
-e 

paulgilbert2000

unread,
Jul 12, 2021, 6:05:56 PM7/12/21
to TiddlyWiki
Thanks again :)

paulgilbert2000

unread,
Jul 13, 2021, 9:16:06 PM7/13/21
to TiddlyWiki
Hi,

OK , i confess, i cant hack this , i don't think i have the necessary skill to do what i want..

what i really want  is a  schedule where i can scooch over appointments to fit one in between existing ones , I think it would be a useful tool for anyone who hectic scheduled and is constantly required to reschedule appointments ,calls or tasks

so if you think this is easy  , or if you are remotely interested that would be great, if not, i am still very grateful for your help either way:)

My Idea was displaying a weeks schedule in  a list filter where every tiddler listed is a task with a start field value and end date field value, and tagged "task"... which i can do easily

then in parallel. have another schedule . again , represented in a list filter , but every tiddler listed is a "Call"with with a start date field value and and end date field value  , and tagged call

and the whole idea is to have some mechanism to work as follows

1-if a call is added in a non vacant slot , then push all tasks with a value equal to the duration of the call
2-if a new task is added in a non vacant slot,   then push all tasks with a value equal to the duration of the task

where
vacant slot = a time space where a tiddler can only hold a start date and an end date value that are not overlapping with in other tiddlers tagged call or  task
non vacant slot= a time space where an existing tiddler already occupies
Duration of a call or duration of a  task =  is the difference between the start and end date field values
Tasks = tiddlers tagged task
Calls =  tiddlers tagged Call

and

calls cannot over lap with other calls
tasks cannot over lap with other tasks
Calls cannot over lap with tasks

also this all assumes there is a start and end and for a working day/week  IE. 9 to 5  excluding sat and sunday

is this generally speaking achievable in tiddly wiki ?

TW Tones

unread,
Jul 13, 2021, 10:51:00 PM7/13/21
to TiddlyWiki
Mohamad,

Unfortunately with this kind of project the "devil is in the details". What I suggest before proceeding is to really think about what you want from this. For example if inserting an item pushes future items away then they were not really (fixed) scheduled but placed in a queue which you are happy to reorder. All you need to store is the time frame they each take and the order in which they are listed, and you can re-generate your time spaced list.

I wanted to do something similar so if I delay start of one activity, or take longer/shorter in one task, this change is reflected in updating my schedule. 

  • What I suggest is create items with a date and the estimated length of task and maintain an ordered list of these. Simply determine the start and end times dynamically. Basically the last end time plus the length of the current.
  • Any given booking could have an enforced start time and/or end times set, and you will need to handle the impact of these.
  • One tip, is the smartest part of your computer or mobile, the operating system, tiddlywiki etc.. is still you. If you make it easy for yourself, visual etc... you can implement quite sophisticated methods yourself even without automation, and any way you may want control of your destiny.
  • By the way don't be too preciouses about the hours as they relate to a date, you can just manage a separate hour field on a day in question.
I will see if I can give this some further thought
Tones

paulgilbert2000

unread,
Jul 18, 2021, 10:35:51 PM7/18/21
to TiddlyWiki
Thanks Tones,

Yes  tasks are not fixed , calls are.

What i really want from this is to push tasks around calls, with tasks being tiddlers tagged "tasks" ,and calls tiddlers tagged "calls".

The idea was
You create a new tiddler tagged "task", with a start date value in a start date field and end date,value in and end date field
You go to a list which has all tasks and call tiddlers <-------  i can do this one :)
You get some visual queue that there is a conflict
You hit a button , and the entire week schedule for tasks (and not calls) is pushed with the duration of the newly inserted task
The schedule push for tasks will inevitably cause new conflicts with calls, which the script should resolve in the same above mentioned manner

I have one question
" All you need to store is the
time frame they each take and the order in which they are listed,"   where and how  would you store information ?to use later for checks/comparisons ? i am asking because i can only use tiddly wiki at the moment to display information only, but not store it :(

also one more question, i have no codding background, what kind of information i should be reading to improve my ability for writing code in tiddly wiki , or perhaps for achieving this specific task i am after

and finally, just out of curiosity if you know , are there people in the forum that can do work on commission?
Reply all
Reply to author
Forward
0 new messages