Fedora Linux Support Community & Resources Center
  #1  
Old 10th May 2017, 05:14 PM
Jeff Sadowski Offline
Registered User
 
Join Date: Jun 2005
Age: 42
Posts: 477
linuxchrome
Code Challenge 20170510090000.0Z to 1494406800

AD ldap output sometimes has variable in the 20170510090000.0Z format. It is nice in scripts to put this in a unix timestamp to do comparisons on.

I was using sed and date but it just doesn't look elegant and I was wanting to know if anyone has a nice looking alternative.

Here is my semi elegant solution

Code:
d () 
{ 
    local mydigits="";
    while [ $# -gt 0 ]; do
        local digits=$1;
        local multiple=1;
        if [ "$(echo $1|sed 's/[0-9]*{[0-9]*}//')" = "" ]; then
            digits=$(echo $1|sed 's/\([0-9]*\).*/\1/');
            multiple=$(echo $1|sed 's/[0-9]*{\([0-9]*\)}/\1/');
        fi;
        while [ ${multiple} -gt 0 ]; do
            mydigits="${mydigits}\\([0-9]\\{$digits\\}\\)";
            multiple=$((${multiple} -1));
        done;
        shift;
    done;
    echo ${mydigits}
}
z2u_match=$(d 4 2{5})
z2u()
{
 # z2u 20170510090000.0Z
 # 1494406800
 if [ "$(echo $1 | sed "s/^$(d 14).0Z$//")" = "" ];then
  date +%s -d "$(echo $1|sed "s/^${z2u_match}.*/\1-\2-\3 \4:\5:\6/") UTC";
 else
  echo 0;
 fi
}
Reasoning:
all the backslashes needed for sed and getting z2u_match was hard to follow. I needed my d function to make it more straight forward.
my d function started with just one input
Code:
z2u_match=$(d 5)$(d 2)$(d 2)$(d 2)$(d 2)$(d 2)
I probably should have stopped there as d was much more elegant, but I had my d function so many times I thought it would be nice in a loop. So I added code to do this
Code:
z2u_match=$(d 5 2 2 2 2 2)
Then I had five 2's in a row and thought it would be nice to be able to short hand.

Maybe there is a shortcut using other standard unix commands?
I'd like to see others solutions.

Last edited by Jeff Sadowski; 10th May 2017 at 09:12 PM.
Reply With Quote
  #2  
Old 10th May 2017, 08:45 PM
Jeff Sadowski Offline
Registered User
 
Join Date: Jun 2005
Age: 42
Posts: 477
linuxchrome
Re: Code Challenge 20170510090000.0Z to 1494428400

Oooh I got to thinking about it and here is another much more elegant solution
Code:
z2u()
{
 # z2u 20170510090000.0Z
 # 1494406800
 if [ "$(echo $1 | sed "s/^[0-9]\{14\}.0Z$//")" = "" ];then
  date +%s -d "${1:0:4}-${1:4:2}-${1:6:2} ${1:8:2}:${1:10:2}:${1:12:2} UTC"
 else
  echo 0;
 fi
}

Last edited by Jeff Sadowski; 10th May 2017 at 09:16 PM.
Reply With Quote
  #3  
Old 10th May 2017, 11:32 PM
RupertPupkin Offline
Registered User
 
Join Date: Nov 2006
Location: Detroit
Posts: 6,559
linuxfedorafirefox
Re: Code Challenge 20170510090000.0Z to 1494428400

Obligatory Java version:
Code:
import java.time.*;
import java.time.format.DateTimeFormatter;

public class ldapzToUnix {
   public static void main(String[] args) {
      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHHmmss[,S][.S]X");
      System.out.println(OffsetDateTime.parse(args[0], dtf).toInstant().getEpochSecond());
   }
}
Compile and run:
Code:
$ javac ldapzToUnix.java
$ java ldapzToUnix 20170510090000.0Z
1494406800
__________________
OS: Fedora 25 x86_64 | Machine: HP Pavilion a6130n | CPU: AMD 64 X2 Dual-Core 5000+ 2.6GHz | RAM: 7GB PC5300 DDR2 | Disk: 400GB SATA | Video: ATI Radeon HD 4350 512MB | Sound: Realtek ALC888S | Ethernet: Realtek RTL8201N

Last edited by RupertPupkin; 11th May 2017 at 12:00 AM. Reason: Simplified a bit
Reply With Quote
  #4  
Old 11th May 2017, 01:47 PM
HaydnH Offline
Registered User
 
Join Date: Feb 2005
Location: London, UK
Posts: 398
windows_7chrome
Re: Code Challenge 20170510090000.0Z to 1494428400

If you're talking scripts then why not just use the date command?

Seconds since epoch to date:

Code:
# date -ud "@1494428400"
Wed 10 May 09:00:00 UTC 2017
Date to seconds since epoch:

Code:
# date -ud "20170510 0900" +%s
1494428400

You'd have to convert "20170510090000.0Z" to "20170510 0900" which is trivial:

Code:
# DATE="20170510090000.0Z"; echo "${DATE:0:8} ${DATE:9:4}"
20170510 0900
Reply With Quote
  #5  
Old 11th May 2017, 05:19 PM
Jeff Sadowski Offline
Registered User
 
Join Date: Jun 2005
Age: 42
Posts: 477
linuxchrome
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by HaydnH View Post
If you're talking scripts then why not just use the date command?

Seconds since epoch to date:

Code:
# date -ud "@1494428400"
Wed 10 May 09:00:00 UTC 2017
Date to seconds since epoch:

Code:
# date -ud "20170510 0900" +%s
1494428400

You'd have to convert "20170510090000.0Z" to "20170510 0900" which is trivial:

Code:
# DATE="20170510090000.0Z"; echo "${DATE:0:8} ${DATE:9:4}"
20170510 0900
Nice I'll have to read more on the input format's I didn't see it yesterday in the man page but now I see it tells me to use "info date" I only knew of the YYYY-mm-dd HH:MM:SS format working.
I'll update my function as follows
Code:
z2u () 
{ 
    if [ $(echo $1|wc -c) -gt 16 ] && [ "$(echo $1 | sed "s/^[0-9]\{14\}.0Z$//")" = "" ]; then
        date +%s -ud "${1:0:8} ${1:8:4}";
    else
        echo 0;
    fi
}

Last edited by Jeff Sadowski; 11th May 2017 at 05:37 PM.
Reply With Quote
  #6  
Old 11th May 2017, 05:34 PM
Jeff Sadowski Offline
Registered User
 
Join Date: Jun 2005
Age: 42
Posts: 477
linuxchrome
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by RupertPupkin View Post
Obligatory Java version:
Code:
import java.time.*;
import java.time.format.DateTimeFormatter;

public class ldapzToUnix {
   public static void main(String[] args) {
      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHHmmss[,S][.S]X");
      System.out.println(OffsetDateTime.parse(args[0], dtf).toInstant().getEpochSecond());
   }
}
Compile and run:
Code:
$ javac ldapzToUnix.java
$ java ldapzToUnix 20170510090000.0Z
1494406800
Nice it is interesting to see date inputs and outputs in different programming languages.
Java looks pretty clean
Reply With Quote
  #7  
Old 11th May 2017, 11:20 PM
RupertPupkin Offline
Registered User
 
Join Date: Nov 2006
Location: Detroit
Posts: 6,559
linuxfedorafirefox
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by HaydnH View Post
If you're talking scripts then why not just use the date command?
The date command would have a little bit of trouble with the general LDAP timestamp format, or at least there'd be a bit more work required. Jeff Sadowski mentioned the format he's seeing from his particular Active Directory server, but there are actually some extra variations allowed, which are described in RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules, in Section 3.3.13 (Generalized Time). The Java program I posted handles all the possible cases.

First, the dot and the digit following it are optional:
Code:
$ java ldapzToUnix 20170510090000.0Z
1494406800

$ java ldapzToUnix 20170510090000Z
1494406800
Second, the dot can be replaced by a comma:
Code:
$ java ldapzToUnix 20170510090000,0Z
1494406800
Third, the digit following the dot (or comma) represents tenths of a second (and hence won't affect the number of seconds since the epoch):
Code:
$ java ldapzToUnix 20170510090000,6Z
1494406800
Lastly, the "Z" at the end represents zero offset from UTC, and can be replaced by any offset of ± 18 hours (i.e. from -1800 to +1800), with the minutes portion of the offset being optional:
Code:
$ java ldapzToUnix 20170510090000.0Z
1494406800

$ java ldapzToUnix 20170510090000.0-0000
1494406800

$ java ldapzToUnix 20170510090000.0-0500
1494424800

$ java ldapzToUnix 20170510090000.0+0500
1494388800

$ java ldapzToUnix 20170510090000.0+05
1494388800

$ java ldapzToUnix 20170510090000+05
1494388800
Of course those additional cases could be handled by a script (a good challenge!), but I think the Java version is simpler and cleaner.
__________________
OS: Fedora 25 x86_64 | Machine: HP Pavilion a6130n | CPU: AMD 64 X2 Dual-Core 5000+ 2.6GHz | RAM: 7GB PC5300 DDR2 | Disk: 400GB SATA | Video: ATI Radeon HD 4350 512MB | Sound: Realtek ALC888S | Ethernet: Realtek RTL8201N
Reply With Quote
  #8  
Old 12th May 2017, 05:34 AM
ocratato Online
Registered User
 
Join Date: Oct 2010
Location: Canberra
Posts: 2,544
linuxfirefox
Re: Code Challenge 20170510090000.0Z to 1494428400

Your Java program may need a tweak,
The offsets at the end mean that the given value is local time, hence a conversion to Unix time (UTC) would require the offset to added/subtracted from the value.
__________________
Has anyone seriously considered that it might be turtles all the way down?
That's very old fashioned thinking.
The current model is that it's holographic nested virtualities of turtles, all the way down.
Reply With Quote
  #9  
Old 12th May 2017, 12:57 PM
HaydnH Offline
Registered User
 
Join Date: Feb 2005
Location: London, UK
Posts: 398
windows_7chrome
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by RupertPupkin View Post
Of course those additional cases could be handled by a script (a good challenge!), but I think the Java version is simpler and cleaner.
I disagree, if you're writing a shell script (as stated in the OP), then why write a java program to be called from that script when a couple of lines of shell will do the job?

The YYYYMMDD part doesn't change from the above, if you want to include the +/-NN00 timezone then you just set the TZ before the date:

Code:
haydnh@hostname:~/test> cat dconv.sh
#!/bin/bash

DATE="$1"
NDATE="${DATE:0:8} ${DATE:8:4}"
TZ=$(echo $DATE |egrep -o "[\+\-].*");

SDATE=$(TZ=":GMT$TZ" date -d "$NDATE" +%s)
echo "Date $DATE converts to: $SDATE"

haydnh@hostname:~/test> ./dconv.sh 20170510090000.0Z
Date 20170510090000.0Z converts to: 1494406800
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0-0000
Date 20170510090000.0-0000 converts to: 1494406800
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0-0500
Date 20170510090000.0-0500 converts to: 1494320400
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+0500
Date 20170510090000.0+0500 converts to: 1494493200
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+05
Date 20170510090000.0+05 converts to: 1494424800
haydnh@hostname:~/test> ./dconv.sh 20170510090000+05
Date 20170510090000+05 converts to: 1494424800
Reply With Quote
  #10  
Old 13th May 2017, 02:41 PM
RupertPupkin Offline
Registered User
 
Join Date: Nov 2006
Location: Detroit
Posts: 6,559
linuxfedorafirefox
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by ocratato View Post
Your Java program may need a tweak,
The offsets at the end mean that the given value is local time, hence a conversion to Unix time (UTC) would require the offset to added/subtracted from the value.
That's what the program does.
Code:
$ java ldapzToUnix 19941216103200Z
787573920

$ java ldapzToUnix 19941216053200-0500
787573920
__________________
OS: Fedora 25 x86_64 | Machine: HP Pavilion a6130n | CPU: AMD 64 X2 Dual-Core 5000+ 2.6GHz | RAM: 7GB PC5300 DDR2 | Disk: 400GB SATA | Video: ATI Radeon HD 4350 512MB | Sound: Realtek ALC888S | Ethernet: Realtek RTL8201N
Reply With Quote
  #11  
Old 13th May 2017, 08:28 PM
RupertPupkin Offline
Registered User
 
Join Date: Nov 2006
Location: Detroit
Posts: 6,559
linuxfedorafirefox
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by HaydnH View Post
Code:
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+0500
Date 20170510090000.0+0500 converts to: 1494493200
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+05
Date 20170510090000.0+05 converts to: 1494424800
Why are those outputs different? The input date and time are the same (20170510090000), and the offsets are the same (+0500 = +05).
__________________
OS: Fedora 25 x86_64 | Machine: HP Pavilion a6130n | CPU: AMD 64 X2 Dual-Core 5000+ 2.6GHz | RAM: 7GB PC5300 DDR2 | Disk: 400GB SATA | Video: ATI Radeon HD 4350 512MB | Sound: Realtek ALC888S | Ethernet: Realtek RTL8201N
Reply With Quote
  #12  
Old 15th May 2017, 01:01 PM
HaydnH Offline
Registered User
 
Join Date: Feb 2005
Location: London, UK
Posts: 398
windows_7chrome
Re: Code Challenge 20170510090000.0Z to 1494428400

Quote:
Originally Posted by RupertPupkin View Post
Why are those outputs different? The input date and time are the same (20170510090000), and the offsets are the same (+0500 = +05).
Good catch, it doesn't recognise 4 digit timezones (:GMT+0500):

Code:
haydnh@hostname:~/test> TZ=":GMT+00" date
Mon May 15 11:56:49 GMT 2017
haydnh@hostname:~/test> TZ=":GMT+05" date
Mon May 15 06:56:52 GMT 2017
haydnh@hostname:~/test> TZ=":GMT+0500" date
Sun May 14 11:56:55 GMT 2017
haydnh@hostname:~/test>

So need to change ".*" to "..":

Code:
haydnh@hostname:~/test> cat dconv.sh
#!/bin/bash

DATE="$1"
NDATE="${DATE:0:8} ${DATE:8:4}"
TZ=$(echo $DATE |egrep -o "[\+\-]..");

SDATE=$(TZ=":GMT$TZ" date -d "$NDATE" +%s)
echo "Date $DATE converts to: $SDATE"

Which works better:

Code:
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+0500
Date 20170510090000.0+0500 converts to: 1494424800
haydnh@hostname:~/test> ./dconv.sh 20170510090000.0+05
Date 20170510090000.0+05 converts to: 1494424800
Reply With Quote
  #13  
Old 22nd May 2017, 07:21 PM
Jeff Sadowski Offline
Registered User
 
Join Date: Jun 2005
Age: 42
Posts: 477
linuxchrome
Re: Code Challenge 20170510090000.0Z to 1494428400

I modified mine to go further in the future or past then my program ever will. But it seems like the format is understood by date down to 0CE and beyond 9999

Code:
z2u()
{
 # z2u 20170510090000.0Z
 # 1494406800
 if [ ${#1} -gt 13 ];then
  # year month day digits
  ymdd=$((${#1}-9))
  date +%s -ud "${1:0:${ymdd}} ${1:${ymdd}:4}" 2>/dev/null||echo 0;
 else
  echo 0;
 fi
}
I'd be curious about a javascript implementation as I always found javascript to be difficult in changing time zones.
Reply With Quote
Reply

Tags
challenge, code

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
HDD configuration challenge gcmartin Hardware & Laptops 2 3rd April 2010 08:33 PM
A challenge... Flounder Wibble 19 9th April 2007 07:56 PM
Any on up to a challenge silvagroup Programming & Packaging 13 23rd October 2006 06:47 PM
i need a new challenge! teethlikelions Fedora Focus 8 14th June 2006 08:01 PM
Are you up to the challenge??? linuxjunkie Using Fedora 15 6th November 2004 02:40 PM


Current GMT-time: 14:10 (Thursday, 29-06-2017)

TopSubscribe to XML RSS for all Threads in all ForumsFedoraForumDotOrg Archive
logo

All trademarks, and forum posts in this site are property of their respective owner(s).
FedoraForum.org is privately owned and is not directly sponsored by the Fedora Project or Red Hat, Inc.

Privacy Policy | Term of Use | Posting Guidelines | Archive | Contact Us | Founding Members

Powered by vBulletin® Copyright ©2000 - 2012, vBulletin Solutions, Inc.

FedoraForum is Powered by RedHat