Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Can I use a seconds datasource integer field to back a TimeItem?

    Hi Fellas, all the best for the new year.

    I'm playing around with a form with a peculiar use case.

    I have a datasource field that has a duration in seconds.
    Code:
    <field name="duration" type="integer" required="false">
    But it's not a great UI to have the user enter the duration in seconds. So, I am trying to have a TimeItem, where the user can enter the duration on the form HH:mm but it gets converted to/from the raw datasourcefield when loading/saving.

    Is this possible or am I getting this wrong? Do I have to make a completely custom CanvasItem?

    Thankful for pointers.

    #2
    Hi mathias1,

    I'd try to work with customUpdateExpression and customSelectExpression.
    I'm not sure what type I'd use, but my hunch is type="time" so that the clientside can do it's magic and just use TimeItem.

    Best regards
    Blama

    Comment


      #3
      Hi,
      I ended up with custom CanvasItem.
      We are not using SmartClient Server, so cannot use customUpdateExpression nor customSelectExpression.
      MichalG

      Comment


        #4
        HI guys, thanks for input! Blama, great idea but I want to do this client side, i.e. send an int value to/from server and do conversion on the client.

        CanvasItem it is, I guess...

        Comment


          #5
          Hi mathias,

          I assume that anything else than type="time" won't work well with TimeItem, so I think with type="integer" you'll have to use a CanvasItem, but I never tried this myself.

          I'd definitely try with customUpdateExpression and customSelectExpression and type="time":
          customSelectExpression: read your integer from the db and convert to time (whatever that looks like)
          customUpdateExpression: convert the client-sent time (whatever that looks like) to integer

          Depending on what the framework does with JDBC because of the type="time" this will work. You need to try it or wait for Isomorphic. If it works it's definitely more elegant than CanvasItem.

          Best regards
          Blama

          Comment


            #6
            Yeah, I'm not using the sc server either, so it's not an option for me.

            Comment


              #7
              The best approach here is to have the field by of type="time" and treat the value as a Time instance pervasively on the client, then do a two-way conversion on the server.

              Mathias, I think your app actually does use the SmartClient Server, you just don't use the SQLDataSource. For you, the best place to handle the two-way conversion would be somewhere in your custom server DataSource implementation, possibly by just adding an extra setter to the relevant bean which takes a Java Date object and updates the integer field on the same bean.

              MichalG, we're not as familiar with your setup, but if you're using RestDataSource, you probably want to do the two-way conversion after your server code has parsed the REST inbound request.

              Either way, using a CanvasItem for editing is definitely a suboptimal solution, because you lose all the other client-side functionality that would do the right thing automatically if away that the value is meant as a time value. This includes filtering, formatting, *When rules, cache sync, and many other subsystems.

              Comment


                #8
                Hey thanks for responding. Yeah I know and I do that kind of conversion in one or two other places. It's just that it's a bunch of data and I had hoped not having to do that conversion back and forth for every object on the server on every request. Thanks for the clarification, appreciated

                Comment


                  #9
                  Hey, when I got cracking on this, I ran into an old problem - if I use LocalTime for time fields, it gets converted somewhere to the zone of the browser, which is not desirable when I want to use it as-is. (for example in this specific thread, to actually use the Time object for hours, minutes)

                  In my current situation, I have a database column called expected, an integer, which is read up into a bean.

                  I have a DS field:
                  Code:
                  <field name="expectedTime" type="time" required="false">
                              <title>
                                  <fmt:message key="expectedTime"/>
                              </title>
                          </field>
                  In my bean, I return this:
                  Code:
                  public LocalTime getExpectedTime(){
                          return LocalTime.ofSecondOfDay(expected);
                      }
                  The local time matches, i.e in the database I have 27600, and the local time is 07:40 when returned from the method.

                  However, the smartgwt called the "getExpectedTime" as expected, but in the browser the value is 08:40, one hour more, since I'm on Swedish time.

                  I've had similar issues with LocalTime and SmartGWT in the past, and back then I finally got around it by doing an additional transformation, LocalTime -> java.util.Date and then it works...

                  I don't think LocalTime should be handled with time zone as a factor, Is there an alternate, better way? Thankful for pointers

                  Comment


                    #10
                    On your previous point about server-side conversion: going back and forth between integer seconds and a Date object is an extremely trivial operation, probably not worth pushing to the client. But if you wanted to anyway, you could do so with DataSource.transformResponse() and still have all UI-layer client-side handling work with a true time representation, allowing all the automatic handling previously mentioned to work as normal.

                    As far as this new problem, take a look at the Data & Time Format and Storage overview. If you declare your field as type "time" and you provide a LocalTime, it would be expected that the time is transmitted as in, and the value is treated as a pure time (without a date or timezone).

                    You've been talking about storing values in seconds and doing some conversion somewhere, so we would look at that code to figure out why there is a time shift.

                    Comment


                      #11
                      OK. so this is what i'm seeing:


                      1. i have a form that is working on "opening hours" each work day.

                      They are Time in the mariaDB database, and i fetch them as LocalTime in my Hibernate entity:
                      Code:
                      @Column(length = 16)
                      LocalTime monstart;
                      2. i have a java transfer object that imports them as LocalTime:
                      Code:
                      LocalTime monstart;
                      LocalTime wedstart;
                      3. in my DS, i have them defined like this:
                      Code:
                      <field name="monstartAsDate" type="time" length="64" hidden="false">
                          <title>
                              <fmt:message key="monstartAsDate"/>
                          </title>
                      </field>
                      So, the reason for "asDate" is this issue I'm talking about. I noticed that they were pushed one hour in the form if I just returned LocalTimes, so in the TO object above I have
                      methods for every field (code simplified):

                      Code:
                      public Date getMonstartAsDate() {
                          return Date.from(monend.atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant());
                      }
                      
                      public void setMonendAsDate(Date monend) {
                          this.monend = Instant.ofEpochMilli(monend.getTime()).atZone(ZoneId.systemDefault()).toLocalTime();
                      }
                      To avoid getting them shifted.

                      ----

                      Now, to exemplify what happens in my network traffic, changed the "getmonstartasdate" from the above, to just return the localtime so that we can compare:

                      Code:
                      public LocalTime getMonstartAsDate() {
                              return monstart;//for this specific field, I don't convert to a Date, just return the LocalTime as-is
                          }
                      If I set a breakpoint in my "fetch" method before handing the TO back to the smartGWT framework here's what it looks like (as you can see, it's 08:00 both on Monday and Wednesday, but I now do not convert the "monster" to a date anymore):
                      Click image for larger version

Name:	Screenshot 2024-01-13 at 12.29.00.png
Views:	93
Size:	56.6 KB
ID:	271519


                      So when i call this, it looks like this in the network request log:

                      the one where i changed to return localtime directly and now gets shifted from 0800 somewhere:
                      monstartAsDate:new Date(28800000) //this is 8 hours in milliseconds but gets translated somewhere

                      the one where i return a java.util.date, which works fine:
                      wedstartAsDate:isc.DateUtil.parseServerTime(8,0,0,0)


                      ...And this results in the form items (Monday is shifted one hour):
                      Click image for larger version

Name:	Screenshot 2024-01-13 at 12.47.30.png
Views:	88
Size:	23.0 KB
ID:	271520

                      I hope this is structured not too incomprehensible :) If you can see that I do anything wrong, I'm all ears!

                      Comment


                        #12
                        Thanks for doing a thorough job explaining how you're getting this result. We'll take a look and see if we can replicate this on our end - it seems to conflict with our tests that show LocalTime converting as expected.

                        We'll try to get back to you later in the week, however, please be patient as there's a lot going on at the moment!

                        Comment


                          #13
                          No problem mate, this particular thing has been like this for a long time and works with my complex workaround (took a bit to get working...)

                          Comment


                            #14
                            Hey, did you ever get the chance to look at this?

                            Comment

                            Working...
                            X