omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Not able to output datetime to text view in Ui.

    Pythonista
    4
    26
    16062
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • JonB
      JonB last edited by

      I think you probably meant to do:
      timecard=v['textview1']
      after you load the view. then, timecard. text.append(...) to add text. actually, you might need to do
      timecard. text += '...', I forget whether text is directly modifiable.

      for storing, you will want to implement a custom view. in did_load, you would read from a file and populate the text. You probably would want to append to the file each time you press the button:

      with open('timecard.txt','a') as f:
          f.write(...)
      
      

      You probably want to add \n each write or append.

      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by JonB

        By the way, posting code to the forum, use triple back tick
        ```
        Around your code to get it to format right

        1 Reply Last reply Reply Quote 0
        • meleyz
          meleyz last edited by

          Ok cool. I will try this out as soon as I can. Thank you. I will post again after my lunch break and let you know if I have any success.

          1 Reply Last reply Reply Quote 0
          • meleyz
            meleyz last edited by

            Still no luck getting a result on the text view. This is where I’m at.

            import datetime
            import appex, ui
            
            oTime = datetime.datetime.now()
            timecard = []
            
            def clock_in(sender):
            	timecard.append(oTime)
            	timecard.append('Clock in successful.')
            	
            def clock_out(sender):
            	timecard.append(oTime)
            	timecard.append('Clock out successful.')
            
            def updateTextView():
            	v = sender.superview
            	timecard = v['textview1']
            	timecard.text += ''
            	
            v = ui.load_view()
            v.present('sheet')
            
            cvp 2 Replies Last reply Reply Quote 0
            • cvp
              cvp @meleyz last edited by cvp

              @meleyz updateTextView does not have a "sender" parameter in your script

              1 Reply Last reply Reply Quote 0
              • cvp
                cvp @meleyz last edited by ccc

                @meleyz

                def updateTextView(sender):
                    print(sender.text)
                
                meleyz 1 Reply Last reply Reply Quote 0
                • JonB
                  JonB last edited by

                  Okay,
                  what class do you think timecard is? If you are not sure, add some print statements to your callbacks, and find out. As a hint, you refer to two completely different variables both called timecard in your code.

                  meleyz 1 Reply Last reply Reply Quote 0
                  • meleyz
                    meleyz @JonB last edited by

                    @JonB

                    Forgive my lack of understanding here as I have only been learning python for about a week now, but you said I was using 2 different variables to define ‘timecard’ but wouldn’t a list be an object and not a variable? Anyways, I’m pretty much dead in the water here because I get what I am looking for in the console however the actual text view itself isnt displaying anything. This is the code I have right now.

                    import datetime
                    import appex, ui
                    
                    oTime = datetime.datetime.now()
                    timecard = []
                    
                    def clock_in(sender):
                    	timecard.append(oTime)
                    	timecard.append('Clock in successful.')
                    	
                    def clock_out(sender):
                    	timecard.append(oTime)
                    	timecard.append('Clock out successful.')
                    
                    def updateTextView(sender):
                    	v = sender.superview
                    	v['textview1'] = timecard(0,len)
                    	print (sender.text)
                    	
                    v = ui.load_view()
                    v.present('sheet')
                    
                    1 Reply Last reply Reply Quote 0
                    • meleyz
                      meleyz @cvp last edited by

                      @cvp

                      I didn’t even notice, thank you! Still no luck however.

                      cvp 1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp @meleyz last edited by cvp

                        @meleyz If I correctly understand what you want...

                        import ui
                        import datetime
                        import appex, ui
                        
                        def oTime():
                            return format(datetime.datetime.now())
                        timecard = []
                        
                        def clock_in(sender):
                            timecard.append(oTime())
                            timecard.append('Clock in successful.')
                            updateTextView()
                            
                        def clock_out(sender):
                            timecard.append(oTime())
                            timecard.append('Clock out successful.')
                            updateTextView()
                        
                        def updateTextView():
                            t = ''
                            for line in timecard:
                                t = t + line + '\n'
                            v['textview1'].text = t
                            
                        v = ui.load_view()
                        v.present('sheet')
                        

                        see

                        meleyz 1 Reply Last reply Reply Quote 1
                        • meleyz
                          meleyz @cvp last edited by

                          @cvp

                          Wow! Exactly! I have to say that this forum has become my new favorite place. Thank you for being so helpful. I can tell I still have much to learn just by looking at how you wrote the same script that I was trying to write only much more tidy (and it actually works). If I may ask, how long have you been writing code and can you offer any advice as far as a newbie such as myself learning code? I am trying to start with the basics but I find some concepts to be slightly confusing (such as trying to understand the concept of everything being an object). I have always been ‘computer savvy’ but Pythonista is the first and only coding experience I have ever had and I am really enjoying it thus far. I appreciate all the effort that has gone into building such a wonderful support system. Thank you again.

                          cvp Phuket2 3 Replies Last reply Reply Quote 0
                          • cvp
                            cvp @meleyz last edited by

                            @meleyz I write code since years but not a lot in object oriented programming languages.
                            I'm really not very good in Python and I've written this little script not as I would do for me but trying to follow your directions.
                            But, in this forum, there are people like @JonB and @zrzka for the technical aspects, like @ccc for an help about nice Python, like @Phuket2 for telling you how to learn Python...
                            This is not a complete list, there are here a lot of marvelous guys, always ready to help you with real skills.

                            1 Reply Last reply Reply Quote 0
                            • Phuket2
                              Phuket2 @meleyz last edited by

                              @meleyz, not to confuse you but datetime is not the easiest modules to work with. Especially as things get a little more complicated. I am doing some things with dates and times at the moment. I am using a module called arrow. The arrow module ships with Pythonista, but the docs for arrow are not built into Pythonista's help file. You can see the docs here. Again, I dont want to confuse you. But there are a number of modules that have been written as replacements/wrappers to the datetime module to simplify working with dates and times. I can see you usage at the moment is quite modest, but you might want to start adding extra functionality.
                              I also love this forum. Very nice place, a lot of nice guys.

                              meleyz 1 Reply Last reply Reply Quote 0
                              • cvp
                                cvp @meleyz last edited by

                                @meleyz if you define the same action "clock" to both buttons, you can use this shorter code

                                import ui
                                import datetime
                                
                                def clock(sender):
                                    v['textview1'].text = v['textview1'].text + 'Clock ' + sender.title + ': ' + format(datetime.datetime.now()) + '\n'
                                    
                                v = ui.load_view()
                                v.present('sheet')```
                                1 Reply Last reply Reply Quote 0
                                • meleyz
                                  meleyz last edited by

                                  @Phuket2
                                  @cvp

                                  Thanks! I was actually wondering that myself, about shortening the code that is. And thank you @Phuket2 for the information and documentation link. I have been trying to absorb as much of the documentation as I can and not just assume that it doesn’t explain things. I’ve noticed several posters mention that the documentation falls short however I have noticed that the documentation is actually quite thorough if you take the time to read and really try to comprehend what it is saying. I will definitely take your advice on the functionality aspect and I am also trying to build good habits when writing code (such as proper format and leaving myself comments to remember what I am doing). This is how the code looks now and I am currently researching how to change the datetime output format to improve user friendliness. @cvp I will shorten the codes on the button functions when I get home from work. Thanks again.

                                  import ui
                                  import datetime
                                  import appex
                                  import ui
                                  
                                  # import the proper modules needed to run script
                                  
                                  
                                  def oTime():
                                  	return format(datetime.datetime.now())
                                  
                                  
                                  timecard = []
                                  
                                  # define a funtion to return the current time and create a container (list) to store current time when buttons are tapped
                                  
                                  
                                  def clock_in(sender):
                                  	timecard.append(oTime())
                                  	timecard.append('Clock in successful.')
                                  	updateTextView()
                                  
                                  
                                  def clock_out(sender):
                                  	timecard.append(oTime())
                                  	timecard.append('Clock out successful.')
                                  	updateTextView()
                                  
                                  
                                  # define funtions for button actions. Note that the funtion call to 'oTime'
                                  
                                  
                                  def updateTextView():
                                  	t = ''
                                  	for line in timecard:
                                  		t = t + line + '\n'
                                  	v['textview1'].text = t
                                  
                                  
                                  # update the textview with the container created in the first function
                                  
                                  v = ui.load_view()
                                  v.present('sheet')
                                  
                                  # load the UI
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • meleyz
                                    meleyz @Phuket2 last edited by

                                    @Phuket2

                                    I found the Arrow module to be much easier to use and the documentation was very helpful. I have updated my code using it. Thanks!

                                    def oTime():
                                    	return arrow.now().format('MMMM DD, YYYY, h:m:s a')
                                    
                                    Phuket2 1 Reply Last reply Reply Quote 1
                                    • Phuket2
                                      Phuket2 @meleyz last edited by

                                      @meleyz , thats great. When it starts getting very useful is when you have to start worrying about about time zones. In this case it appears that time zones are not important for you. From what I have read and seen etc, the best strategy if you are saving date/times is to save them in utc format (timeoffset +0). Then when you need to display your datetime (arrow object) convert the utc time to your time zone. It's a few extra steps, but arrow makes it very easy.
                                      You have the utc = arrow.utcnow() method and the utc.to('Asia/Bangkok') or utc.to('local') methods. You can also use the utc.for_json() method or str(utc) to write the arrow object datetime as a string to your text file. When you read the text back in you can use the utc = arrow.get(datetime_text_from_file).
                                      Maybe this comment seems over the top. If this is the only thing you every do with datetimes , then it probably is. But if you plan to work with dates and times more, from what I can see the safest bet is only ever save utc times and then convert them into the appropriate Timezone.
                                      Maybe others disagree, not sure. But I find dates and times find there way into projects many times. Good to have a std approach and one will work on web servers etc. Imagine you call arrow.now() on a server somewhere in the world. The result could be anything depending on the servers settings.
                                      Again, i just bring it up as it was something I struggled with when I was/am working with dates and times.

                                      meleyz 1 Reply Last reply Reply Quote 0
                                      • meleyz
                                        meleyz @Phuket2 last edited by

                                        @Phuket2

                                        I think you answered one of my questions before I even had a chance to ask it. And no it is not over the top it is exactly the type of information I am looking for so thank you! I am trying to add a switch to the UI to change between 24 hour format and regular format however I am getting a type error ‘must be str not function ‘ and I am a little confused. Perhaps I am calling the function incorrectly of I have not used the proper statement. I have tried a for statement as well as a while loop and am seeing 2 different errors. The one I just described and a positional argument error on the oTime function. I will comment in the code which line is returning the type error.

                                        import ui
                                        import arrow
                                        import appex
                                        import ui
                                        
                                        # import the proper modules needed to run script
                                        
                                        
                                        a = arrow.now().format('MMMM DD,YYYY, h:m:s a')
                                        b = arrow.now().format('MMMM DD, YYYY, HH:mm:ss A')
                                        
                                        
                                        def oTime(self):
                                        	while oTime(self):
                                        		return (a)
                                        	else:
                                        			return (b)
                                        		
                                        
                                        
                                        timecard = []
                                        
                                        # define a funtion to return the current time and create a container (list) to store current time when buttons are tapped
                                        
                                        
                                        def clock_in(sender):
                                        	timecard.append(oTime)
                                        	timecard.append('Clock in successful.')
                                        	updateTextView()
                                        
                                        
                                        def clock_out(sender):
                                        	timecard.append(oTime)
                                        	timecard.append('Clock out successful.')
                                        	updateTextView()
                                        
                                        
                                        # define funtions for button actions. Note that the funtion call to 'oTime'
                                        
                                        
                                        def updateTextView():
                                        	t = ''
                                        	for line in timecard:
                                        		t = t + line + '\n' # this line is returning the type error must be str not function
                                        	v['textview1'].text = t
                                        
                                        
                                        # update the textview with the container created in the first function
                                        
                                        v = ui.load_view()
                                        v.present('sheet')
                                        
                                        # load the UI
                                        
                                        Phuket2 1 Reply Last reply Reply Quote 0
                                        • JonB
                                          JonB last edited by

                                          oTime is a function. Thus, append(oTime) is trying to append a function. You want append( oTime() ).

                                          Of course, your oTime function is going to tive you some infinite recursion problems!

                                          1 Reply Last reply Reply Quote 1
                                          • Phuket2
                                            Phuket2 @meleyz last edited by

                                            @meleyz, I think the below should help. No need to make 2 instances of the arrow object. Also the formatting can be applied in different parts of your code, depending what makes sense for you. In your case, really you dont need the function oTime. As you did in your code you can call the method in place.

                                            Also your calls to timecard.append(oTime) should be timecard.append(oTime()). You are calling a function, so you need to add the ().

                                            But the timecard.append could look like
                                            timecard.append(arrow.now().format('MMMM DD,YYYY, h:m:s a') or using a _fmt1 for example based on a variable

                                            import arrow
                                            
                                            _fmt1 = 'MMMM DD,YYYY, h:m:s a'
                                            _fmt2 = 'MMMM DD, YYYY, HH:mm:ss A'
                                            
                                            def oTime(fmt=None):
                                                # if no fmt param supplied, return the str version of the arrow
                                                # oject, otherwise return the formatted version
                                                return arrow.now().format(fmt) if fmt else str(arrow.now())
                                                '''
                                                while oTime(self):
                                                    return (a)
                                                else:
                                                        return (b)
                                                '''
                                            print(oTime())
                                            print(oTime(_fmt1))
                                            print(oTime(_fmt2))
                                            

                                            A more complete example

                                            import ui
                                            import arrow
                                            
                                            
                                            class MyClass(ui.View):
                                                def __init__(self, *args, **kwargs):
                                                    super().__init__(*args, **kwargs)
                                                    self.lb = None
                                                    self.sw = None
                                                    self.fmts = ['MMMM DD,YYYY, h:m:s a', 'MMMM DD, YYYY, HH:mm:ss A']
                                                    self.make_view()
                                                    self.update()
                                                    self.update_interval = 1
                                            
                                                def make_view(self):
                                                    # create label
                                                    lb = ui.Label(width=self.width,
                                                                  height=32,
                                                                  alignment=ui.ALIGN_CENTER)
                                                    self.lb = lb
                                                    self.add_subview(self.lb)
                                            
                                                    # create switch
                                                    sw = ui.Switch(action=self.update)
                                                    sw.y = lb.frame.max_y + 10
                                                    sw.x = 10
                                                    self.sw = sw
                                                    self.add_subview(sw)
                                            
                                                def update(self, sender=None):
                                                    '''
                                                    int(self.sw.value) coerce False/True to 0 or 1
                                                    '''
                                                    self.lb.text = str(arrow.now().format(self.fmts[int(self.sw.value)]))
                                            
                                            
                                            if __name__ == '__main__':
                                                f = (0, 0, 300, 400)
                                                v = MyClass(frame=f, bg_color='white')
                                                v.present(style='sheet')
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors