Jenkins sort method behaviour not as expected - sorting
I'm getting different results in jenkins pipeline when trying to sort a list compared to jenkins script console.
Jenkins version: 2.134
groovy version: 2.4.11
Code
def items = [[1, "09-Aug-2018 11:13" ],
[2, "11-Jul-2018 13:27" ],
[3, "02-Oct-2018 15:48" ],
[4, "03-Sep-2018 14:27" ],
[5, "08-Sep-2018 10:07" ],
[6, "11-Jul-2018 14:06" ],
[7, "08-Sep-2018 10:16" ],
[8, "09-Aug-2018 09:53" ],
[9, "16-Jul-2018 12:59" ],
[10, "08-Aug-2018 15:14" ],
[11, "12-Jul-2018 09:04" ],
[12, "08-Aug-2018 14:32" ],
[13, "08-Sep-2018 10:59" ],
[14, "08-Sep-2018 09:50" ],
[15, "16-Aug-2018 09:12" ],
[16, "19-Sep-2018 09:59" ],
[17, "18-Jul-2018 10:25" ],
[18, "11-Sep-2018 14:45" ],
[19, "12-Jul-2018 09:36" ],
[20, "02-Oct-2018 09:18" ]]
def itemsDateNotString = items.collect { [it[0], new Date().parse("dd-MMM-yyyy H:m", it[1])] }
println(itemsDateNotString)
def itemsSorted = itemsDateNotString.sort{ it[1] }
println(itemsSorted)
def itemsSortedReversed = itemsSorted.reverse()
println(itemsSortedReversed)
Results on my laptop and on Jenkins script console:
itemsDateNotString
[[1, Thu Aug 09 11:13:00 GMT 2018], [2, Wed Jul 11 13:27:00 GMT 2018], [3, Tue Oct 02 15:48:00 GMT 2018], [4, Mon Sep 03 14:27:00 GMT 2018], [5, Sat Sep 08 10:07:00 GMT 2018], [6, Wed Jul 11 14:06:00 GMT 2018], [7, Sat Sep 08 10:16:00 GMT 2018], [8, Thu Aug 09 09:53:00 GMT 2018], [9, Mon Jul 16 12:59:00 GMT 2018], [10, Wed Aug 08 15:14:00 GMT 2018], [11, Thu Jul 12 09:04:00 GMT 2018], [12, Wed Aug 08 14:32:00 GMT 2018], [13, Sat Sep 08 10:59:00 GMT 2018], [14, Sat Sep 08 09:50:00 GMT 2018], [15, Thu Aug 16 09:12:00 GMT 2018], [16, Wed Sep 19 09:59:00 GMT 2018], [17, Wed Jul 18 10:25:00 GMT 2018], [18, Tue Sep 11 14:45:00 GMT 2018], [19, Thu Jul 12 09:36:00 GMT 2018], [20, Tue Oct 02 09:18:00 GMT 2018]]
itemsSorted:
[[2, Wed Jul 11 13:27:00 GMT 2018], [6, Wed Jul 11 14:06:00 GMT 2018], [11, Thu Jul 12 09:04:00 GMT 2018], [19, Thu Jul 12 09:36:00 GMT 2018], [9, Mon Jul 16 12:59:00 GMT 2018], [17, Wed Jul 18 10:25:00 GMT 2018], [12, Wed Aug 08 14:32:00 GMT 2018], [10, Wed Aug 08 15:14:00 GMT 2018], [8, Thu Aug 09 09:53:00 GMT 2018], [1, Thu Aug 09 11:13:00 GMT 2018], [15, Thu Aug 16 09:12:00 GMT 2018], [4, Mon Sep 03 14:27:00 GMT 2018], [14, Sat Sep 08 09:50:00 GMT 2018], [5, Sat Sep 08 10:07:00 GMT 2018], [7, Sat Sep 08 10:16:00 GMT 2018], [13, Sat Sep 08 10:59:00 GMT 2018], [18, Tue Sep 11 14:45:00 GMT 2018], [16, Wed Sep 19 09:59:00 GMT 2018], [20, Tue Oct 02 09:18:00 GMT 2018], [3, Tue Oct 02 15:48:00 GMT 2018]]
itemsSortedReversed:
[[3, Tue Oct 02 15:48:00 GMT 2018], [20, Tue Oct 02 09:18:00 GMT 2018], [16, Wed Sep 19 09:59:00 GMT 2018], [18, Tue Sep 11 14:45:00 GMT 2018], [13, Sat Sep 08 10:59:00 GMT 2018], [7, Sat Sep 08 10:16:00 GMT 2018], [5, Sat Sep 08 10:07:00 GMT 2018], [14, Sat Sep 08 09:50:00 GMT 2018], [4, Mon Sep 03 14:27:00 GMT 2018], [15, Thu Aug 16 09:12:00 GMT 2018], [1, Thu Aug 09 11:13:00 GMT 2018], [8, Thu Aug 09 09:53:00 GMT 2018], [10, Wed Aug 08 15:14:00 GMT 2018], [12, Wed Aug 08 14:32:00 GMT 2018], [17, Wed Jul 18 10:25:00 GMT 2018], [9, Mon Jul 16 12:59:00 GMT 2018], [19, Thu Jul 12 09:36:00 GMT 2018], [11, Thu Jul 12 09:04:00 GMT 2018], [6, Wed Jul 11 14:06:00 GMT 2018], [2, Wed Jul 11 13:27:00 GMT 2018]]
However when I run this code as part of the jenkins pipeline it thows and exception and the results are below:
itemsDateNotString
[[1, Thu Aug 09 11:13:00 GMT 2018], [2, Wed Jul 11 13:27:00 GMT 2018], [3, Tue Oct 02 15:48:00 GMT 2018], [4, Mon Sep 03 14:27:00 GMT 2018], [5, Sat Sep 08 10:07:00 GMT 2018], [6, Wed Jul 11 14:06:00 GMT 2018], [7, Sat Sep 08 10:16:00 GMT 2018], [8, Thu Aug 09 09:53:00 GMT 2018], [9, Mon Jul 16 12:59:00 GMT 2018], [10, Wed Aug 08 15:14:00 GMT 2018], [11, Thu Jul 12 09:04:00 GMT 2018], [12, Wed Aug 08 14:32:00 GMT 2018], [13, Sat Sep 08 10:59:00 GMT 2018], [14, Sat Sep 08 09:50:00 GMT 2018], [15, Thu Aug 16 09:12:00 GMT 2018], [16, Wed Sep 19 09:59:00 GMT 2018], [17, Wed Jul 18 10:25:00 GMT 2018], [18, Tue Sep 11 14:45:00 GMT 2018], [19, Thu Jul 12 09:36:00 GMT 2018], [20, Tue Oct 02 09:18:00 GMT 2018]]
itemsSorted:
Wed Jul 11 13:27:00 GMT 2018
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // podTemplate
[Pipeline] End of Pipeline
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.util.Date.reverse() is applicable for argument types: () values: []
Possible solutions: every(), every(groovy.lang.Closure), before(java.util.Date), parse(java.lang.String), parse(java.lang.String, java.lang.String), parse(java.lang.String, java.lang.String, java.util.TimeZone)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
at tmpDeleteArtifacts.printItems(<PATH>)
at tmpDeleteArtifacts.call(<PATH>)
at standardPipeline.call(<PATH>)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77)
at sun.reflect.GeneratedMethodAccessor251.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
Provided that the code works on jenkins script consolei'm not sure why the pipeline is giving different results. I believe it's the sort function because I would expect it to sort the list in date order however it is returning an single date in the pipeline whereas the script console is returning the sorted list.
Thanks in advance,
Jay.
It happens to you, because you run list transformation in Groovy CPS mode, which has plenty of limitations when running in continuation passing style. Solution is fairly simple - extract your Groovy code to a function annotated with #NonCPS so Jenkins executes it outside CPS mode. Take a look at this simple example:
Jenkinsfile:
node {
stage("Test") {
def items = [[1, "09-Aug-2018 11:13" ],
[2, "11-Jul-2018 13:27" ],
[3, "02-Oct-2018 15:48" ],
[4, "03-Sep-2018 14:27" ],
[5, "08-Sep-2018 10:07" ],
[6, "11-Jul-2018 14:06" ],
[7, "08-Sep-2018 10:16" ],
[8, "09-Aug-2018 09:53" ],
[9, "16-Jul-2018 12:59" ],
[10, "08-Aug-2018 15:14" ],
[11, "12-Jul-2018 09:04" ],
[12, "08-Aug-2018 14:32" ],
[13, "08-Sep-2018 10:59" ],
[14, "08-Sep-2018 09:50" ],
[15, "16-Aug-2018 09:12" ],
[16, "19-Sep-2018 09:59" ],
[17, "18-Jul-2018 10:25" ],
[18, "11-Sep-2018 14:45" ],
[19, "12-Jul-2018 09:36" ],
[20, "02-Oct-2018 09:18" ]]
sortExample(items)
}
}
#NonCPS
def sortExample(items) {
def itemsDateNotString = items.collect { [it[0], new Date().parse("dd-MMM-yyyy H:m", it[1])] }
println(itemsDateNotString)
def itemsSorted = itemsDateNotString.sort{ it[1] }
println(itemsSorted)
def itemsSortedReversed = itemsSorted.reverse()
println(itemsSortedReversed)
}
Output:
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/test-pipeline
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] echo
[[1, Thu Aug 09 11:13:00 UTC 2018], [2, Wed Jul 11 13:27:00 UTC 2018], [3, Tue Oct 02 15:48:00 UTC 2018], [4, Mon Sep 03 14:27:00 UTC 2018], [5, Sat Sep 08 10:07:00 UTC 2018], [6, Wed Jul 11 14:06:00 UTC 2018], [7, Sat Sep 08 10:16:00 UTC 2018], [8, Thu Aug 09 09:53:00 UTC 2018], [9, Mon Jul 16 12:59:00 UTC 2018], [10, Wed Aug 08 15:14:00 UTC 2018], [11, Thu Jul 12 09:04:00 UTC 2018], [12, Wed Aug 08 14:32:00 UTC 2018], [13, Sat Sep 08 10:59:00 UTC 2018], [14, Sat Sep 08 09:50:00 UTC 2018], [15, Thu Aug 16 09:12:00 UTC 2018], [16, Wed Sep 19 09:59:00 UTC 2018], [17, Wed Jul 18 10:25:00 UTC 2018], [18, Tue Sep 11 14:45:00 UTC 2018], [19, Thu Jul 12 09:36:00 UTC 2018], [20, Tue Oct 02 09:18:00 UTC 2018]]
[Pipeline] echo
[[2, Wed Jul 11 13:27:00 UTC 2018], [6, Wed Jul 11 14:06:00 UTC 2018], [11, Thu Jul 12 09:04:00 UTC 2018], [19, Thu Jul 12 09:36:00 UTC 2018], [9, Mon Jul 16 12:59:00 UTC 2018], [17, Wed Jul 18 10:25:00 UTC 2018], [12, Wed Aug 08 14:32:00 UTC 2018], [10, Wed Aug 08 15:14:00 UTC 2018], [8, Thu Aug 09 09:53:00 UTC 2018], [1, Thu Aug 09 11:13:00 UTC 2018], [15, Thu Aug 16 09:12:00 UTC 2018], [4, Mon Sep 03 14:27:00 UTC 2018], [14, Sat Sep 08 09:50:00 UTC 2018], [5, Sat Sep 08 10:07:00 UTC 2018], [7, Sat Sep 08 10:16:00 UTC 2018], [13, Sat Sep 08 10:59:00 UTC 2018], [18, Tue Sep 11 14:45:00 UTC 2018], [16, Wed Sep 19 09:59:00 UTC 2018], [20, Tue Oct 02 09:18:00 UTC 2018], [3, Tue Oct 02 15:48:00 UTC 2018]]
[Pipeline] echo
[[3, Tue Oct 02 15:48:00 UTC 2018], [20, Tue Oct 02 09:18:00 UTC 2018], [16, Wed Sep 19 09:59:00 UTC 2018], [18, Tue Sep 11 14:45:00 UTC 2018], [13, Sat Sep 08 10:59:00 UTC 2018], [7, Sat Sep 08 10:16:00 UTC 2018], [5, Sat Sep 08 10:07:00 UTC 2018], [14, Sat Sep 08 09:50:00 UTC 2018], [4, Mon Sep 03 14:27:00 UTC 2018], [15, Thu Aug 16 09:12:00 UTC 2018], [1, Thu Aug 09 11:13:00 UTC 2018], [8, Thu Aug 09 09:53:00 UTC 2018], [10, Wed Aug 08 15:14:00 UTC 2018], [12, Wed Aug 08 14:32:00 UTC 2018], [17, Wed Jul 18 10:25:00 UTC 2018], [9, Mon Jul 16 12:59:00 UTC 2018], [19, Thu Jul 12 09:36:00 UTC 2018], [11, Thu Jul 12 09:04:00 UTC 2018], [6, Wed Jul 11 14:06:00 UTC 2018], [2, Wed Jul 11 13:27:00 UTC 2018]]
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
"Use #NonCPS-annotated functions for slightly more complex work. This means more involved processing, logic, and transformations. This lets you leverage additional Groovy & functional features for more powerful, concise, and performant code."
Source: https://jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/
Related
Calculate end date from start date and days per week data
I have the following variables INPUT start_date = 1 JUN 2020 session_days = [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] sessions_per_week_count = 7 # from above data total sesions = 20 OUTPUT 20 JUN 2020 from the above data, we can calculate that end_date should be 20 Jun 2018 I need help writing algorithm/formula to calculate the end date with variable input data based on the calender. any suggestions will be appreciated.
Finally, I came up with a pretty simple method in ruby def session_dates(date, weekdays_arr, number_of_working_days) result = [] while result.size < number_of_working_days if weekdays_arr.include? date.wday result << date end date += 1 end result end by calling a method like this start_date = Date.today.beginning_of_month session_days_in_week = [0,1,2,3,4,5,6] # week starts from 0(Sunday) result = session_dates(start_date, session_days_in_week, 20) I can get all dates on the weekdays in output [ [ 0] Mon, 01 Jun 2020, [ 1] Tue, 02 Jun 2020, [ 2] Wed, 03 Jun 2020, [ 3] Thu, 04 Jun 2020, [ 4] Fri, 05 Jun 2020, [ 5] Sat, 06 Jun 2020, [ 6] Sun, 07 Jun 2020, [ 7] Mon, 08 Jun 2020, [ 8] Tue, 09 Jun 2020, [ 9] Wed, 10 Jun 2020, [10] Thu, 11 Jun 2020, [11] Fri, 12 Jun 2020, [12] Sat, 13 Jun 2020, [13] Sun, 14 Jun 2020, [14] Mon, 15 Jun 2020, [15] Tue, 16 Jun 2020, [16] Wed, 17 Jun 2020, [17] Thu, 18 Jun 2020, [18] Fri, 19 Jun 2020, [19] Sat, 20 Jun 2020 ] and obviously the last element in result array is ending_date.
How should I load resources from src/main/resources in Kotlin?
I'm working on a Spring Boot application written in Kotlin (using Maven), and everything works fine but after generating the jar of my application, it throws an Exception because it can't find the folder src/main/resources: Caused by: java.io.FileNotFoundException: src\main\resources\data\circuits-arrets.json I read that could be because I use File class, and it doesn't work properly after generating the jar. Here's how I read my file: var line: String? val bufferedReader = BufferedReader(FileReader(File(csvLocation))) do { line = bufferedReader.readLine() if (line != null) { //Do something with 'line' } } while (line != null) I found some solutions using InputStream instead of File in the BufferedReader. My question is: Does it really change something for the jar? If yes, how should I do then? Thank you in advance. EDIT: Here's the output of the command jar tvf my-jar.jar : 0 Fri Feb 15 10:34:14 CET 2019 META-INF/ 552 Fri Feb 15 10:34:14 CET 2019 META-INF/MANIFEST.MF 0 Fri Feb 15 10:34:14 CET 2019 org/ 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/ 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/ 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/loader/ 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/loader/data/ 2688 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/loader/jar/ 9736 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarURLConnection.class 1374 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFile$JarFileType.class 14915 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFile.class 3414 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarEntry.class 345 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/FileHeader.class 3172 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/StringSequence.class 4976 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/AsciiBytes.class 1593 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFileEntries$1.class 1997 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class 10728 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFileEntries.class 540 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/CentralDirectoryVisitor.class 299 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarEntryFilter.class 5267 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class 3116 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class 4624 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/CentralDirectoryParser.class 1693 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/ZipInflaterInputStream.class 11509 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/Handler.class 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/loader/archive/ 302 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/Archive$Entry.class 437 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/Archive$EntryFilter.class 945 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/Archive.class 1487 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator$EntryComparator.class 3837 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator.class 5243 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/ExplodedArchive.class 1484 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class 19737 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/PropertiesLauncher.class 282 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/data/RandomAccessDataFile$1.class 2062 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFile$1.class 1233 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarFile$2.class 3263 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class 4015 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/data/RandomAccessDataFile.class 1102 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class 1081 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class 7336 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/JarFileArchive.class 1502 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/MainMethodRunner.class 3608 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/ExecutableArchiveLauncher.class 0 Fri Feb 15 10:34:14 CET 2019 org/springframework/boot/loader/util/ 5203 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/util/SystemPropertyUtils.class 485 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/data/RandomAccessData.class 273 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/ExplodedArchive$1.class 1779 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class 1953 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class 266 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/PropertiesLauncher$1.class 4684 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/Launcher.class 1721 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/WarLauncher.class 1585 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/JarLauncher.class 1527 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class 5687 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/LaunchedURLClassLoader.class 616 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/Bytes.class 702 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarURLConnection$1.class 4306 Wed May 09 13:32:20 CEST 2018 org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class 0 Fri Feb 15 10:34:14 CET 2019 BOOT-INF/ 0 Fri Feb 15 10:34:14 CET 2019 BOOT-INF/classes/ 0 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/constants/ 0 Fri Feb 15 10:33:50 CET 2019 BOOT-INF/classes/data/ 0 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/ 0 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/entities/ 0 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/jsonEntities/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/entities/viewModels/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/repositories/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/security/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/services/ 0 Fri Feb 15 10:34:10 CET 2019 BOOT-INF/classes/fr/asi/utils/ 0 Fri Feb 15 10:34:12 CET 2019 META-INF/maven/ 0 Fri Feb 15 10:34:12 CET 2019 META-INF/maven/com.auth0.samples/ 0 Fri Feb 15 10:34:12 CET 2019 META-INF/maven/com.auth0.samples/kotlin-spring-boot/ 584 Fri Feb 15 10:33:50 CET 2019 BOOT-INF/classes/application.properties 87499 Fri Feb 15 10:33:50 CET 2019 BOOT-INF/classes/data/circuits-arrets.json 261015 Fri Feb 15 10:33:50 CET 2019 BOOT-INF/classes/data/tan-arrets.csv 1029 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/Configuration.class 3471 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/ApplicationUserController.class 6013 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/BaseController.class 1701 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/BikeStationController.class 1692 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/BusStationController.class 612 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/FavoriteController$WhenMappings.class 5385 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/FavoriteController.class 1778 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/LineController.class 7389 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/controllers/StationController.class 1868 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/entities/jsonEntities/Arret.class 1079 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/entities/jsonEntities/BusLineLibelle.class 3252 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/ApplicationUser.class 2977 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/BikeStation.class 2140 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/Favorite.class 2981 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/Station.class 1195 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/entities/viewModels/BaseVM.class 3691 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/entities/viewModels/StationVM.class 1663 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/KotlinSpringBootApplicationKt.class 812 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/repositories/BaseRepository.class 702 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/repositories/BusStationRepository.class 672 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/repositories/LineRepository.class 5530 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/security/JWTAuthenticationFilter.class 2578 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/security/UserDetailsServiceImpl.class 4617 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/services/BaseService.class 1186 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/services/LineService.class 5525 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/StartingDataInjector.class 7943 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/utils/ParsersKt.class 121 Fri Feb 15 10:34:08 CET 2019 META-INF/kotlin-spring-boot.kotlin_module 7216 Fri Feb 15 10:31:38 CET 2019 META-INF/maven/com.auth0.samples/kotlin-spring-boot/pom.xml 1693 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/constants/ConstantsKt.class 1805 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/AccessCondition.class 1065 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/BaseEntity.class 3506 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/BusStation.class 1434 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/FavoriteType.class 2945 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/Line.class 2056 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/entities/mainEntities/StationType.class 2081 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/entities/viewModels/LineVM.class 613 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/KotlinSpringBootApplication.class 1101 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/repositories/ApplicationUserRepository.class 707 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/repositories/BikeStationRepository.class 692 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/repositories/FavoriteRepository.class 687 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/repositories/StationRepository.class 4738 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/security/JWTAuthorizationFilter.class 6776 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/security/WebSecurity.class 1235 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/services/BikeStationService.class 1228 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/services/BusStationService.class 1207 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/services/StationService.class 2405 Fri Feb 15 10:34:06 CET 2019 BOOT-INF/classes/fr/asi/utils/FindersKt.class 5205 Fri Feb 15 10:34:08 CET 2019 BOOT-INF/classes/fr/asi/VMUtils.class 114 Fri Feb 15 10:34:12 CET 2019 META-INF/maven/com.auth0.samples/kotlin-spring-boot/pom.properties 29487 Fri Feb 15 10:33:50 CET 2019 BOOT-INF/classes/data/stations-velos-libre-service-nantes-metropole.csv 0 Fri Feb 15 10:34:14 CET 2019 BOOT-INF/lib/ 628 Wed May 09 13:41:28 CEST 2018 BOOT-INF/lib/spring-boot-starter-data-jpa-2.0.2.RELEASE.jar 593 Wed May 09 13:30:56 CEST 2018 BOOT-INF/lib/spring-boot-starter-2.0.2.RELEASE.jar 927496 Wed May 09 13:19:02 CEST 2018 BOOT-INF/lib/spring-boot-2.0.2.RELEASE.jar 1161361 Wed May 09 13:25:34 CEST 2018 BOOT-INF/lib/spring-boot-autoconfigure-2.0.2.RELEASE.jar 613 Wed May 09 13:30:56 CEST 2018 BOOT-INF/lib/spring-boot-starter-logging-2.0.2.RELEASE.jar 290339 Fri Mar 31 21:27:54 CEST 2017 BOOT-INF/lib/logback-classic-1.2.3.jar 471901 Fri Mar 31 21:27:16 CEST 2017 BOOT-INF/lib/logback-core-1.2.3.jar 17519 Sun Nov 19 01:08:44 CET 2017 BOOT-INF/lib/log4j-to-slf4j-2.10.0.jar 255485 Sun Nov 19 00:48:58 CET 2017 BOOT-INF/lib/log4j-api-2.10.0.jar 4596 Thu Mar 16 17:37:48 CET 2017 BOOT-INF/lib/jul-to-slf4j-1.7.25.jar 26586 Wed Feb 21 15:54:16 CET 2018 BOOT-INF/lib/javax.annotation-api-1.3.2.jar 297518 Sat Oct 14 11:44:44 CEST 2017 BOOT-INF/lib/snakeyaml-1.19.jar 600 Wed May 09 13:41:20 CEST 2018 BOOT-INF/lib/spring-boot-starter-aop-2.0.2.RELEASE.jar 1930381 Wed Nov 15 11:26:54 CET 2017 BOOT-INF/lib/aspectjweaver-1.8.13.jar 598 Wed May 09 13:41:22 CEST 2018 BOOT-INF/lib/spring-boot-starter-jdbc-2.0.2.RELEASE.jar 143471 Thu Apr 05 17:30:38 CEST 2018 BOOT-INF/lib/HikariCP-2.7.9.jar 401279 Tue May 08 08:06:44 CEST 2018 BOOT-INF/lib/spring-jdbc-5.0.6.RELEASE.jar 6739203 Thu Apr 26 11:06:04 CEST 2018 BOOT-INF/lib/hibernate-core-5.2.17.Final.jar 66469 Wed Feb 14 13:23:28 CET 2018 BOOT-INF/lib/jboss-logging-3.3.2.Final.jar 113371 Fri Jul 26 12:01:34 CEST 2013 BOOT-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar 739582 Tue Oct 10 18:04:58 CEST 2017 BOOT-INF/lib/javassist-3.22.0-GA.jar 445288 Wed Sep 06 11:15:06 CEST 2006 BOOT-INF/lib/antlr-2.7.7.jar 186741 Tue Aug 02 13:41:56 CEST 2016 BOOT-INF/lib/jandex-2.0.3.Final.jar 65100 Sat Sep 09 14:47:28 CEST 2017 BOOT-INF/lib/classmate-1.3.4.jar 313898 Mon May 16 14:19:12 CEST 2005 BOOT-INF/lib/dom4j-1.6.1.jar 75288 Tue Nov 24 15:03:08 CET 2015 BOOT-INF/lib/hibernate-commons-annotations-5.0.1.Final.jar 30724 Mon May 13 15:11:34 CEST 2013 BOOT-INF/lib/javax.transaction-api-1.2.jar 335660 Tue May 08 14:29:02 CEST 2018 BOOT-INF/lib/spring-data-jpa-2.0.7.RELEASE.jar 1076871 Tue May 08 14:23:50 CEST 2018 BOOT-INF/lib/spring-data-commons-2.0.7.RELEASE.jar 191789 Tue May 08 08:07:28 CEST 2018 BOOT-INF/lib/spring-orm-5.0.6.RELEASE.jar 255201 Tue May 08 08:06:38 CEST 2018 BOOT-INF/lib/spring-tx-5.0.6.RELEASE.jar 41203 Thu Mar 16 17:36:32 CET 2017 BOOT-INF/lib/slf4j-api-1.7.25.jar 46745 Tue May 08 08:08:48 CEST 2018 BOOT-INF/lib/spring-aspects-5.0.6.RELEASE.jar 588 Wed May 09 13:41:32 CEST 2018 BOOT-INF/lib/spring-boot-starter-web-2.0.2.RELEASE.jar 645 Wed May 09 13:41:30 CEST 2018 BOOT-INF/lib/spring-boot-starter-json-2.0.2.RELEASE.jar 33392 Mon Mar 26 15:55:48 CEST 2018 BOOT-INF/lib/jackson-datatype-jdk8-2.9.5.jar 99630 Mon Mar 26 15:56:26 CEST 2018 BOOT-INF/lib/jackson-datatype-jsr310-2.9.5.jar 8646 Mon Mar 26 15:54:04 CEST 2018 BOOT-INF/lib/jackson-module-parameter-names-2.9.5.jar 591 Wed May 09 13:41:32 CEST 2018 BOOT-INF/lib/spring-boot-starter-tomcat-2.0.2.RELEASE.jar 3115994 Fri Apr 27 21:24:52 CEST 2018 BOOT-INF/lib/tomcat-embed-core-8.5.31.jar 240244 Fri Apr 27 21:24:54 CEST 2018 BOOT-INF/lib/tomcat-embed-el-8.5.31.jar 256776 Fri Apr 27 21:24:54 CEST 2018 BOOT-INF/lib/tomcat-embed-websocket-8.5.31.jar 1130724 Tue Mar 27 09:03:18 CEST 2018 BOOT-INF/lib/hibernate-validator-6.0.9.Final.jar 93107 Tue Dec 19 16:23:28 CET 2017 BOOT-INF/lib/validation-api-2.0.1.Final.jar 1254097 Tue May 08 08:07:04 CEST 2018 BOOT-INF/lib/spring-web-5.0.6.RELEASE.jar 789889 Tue May 08 08:07:52 CEST 2018 BOOT-INF/lib/spring-webmvc-5.0.6.RELEASE.jar 604 Wed May 09 13:41:42 CEST 2018 BOOT-INF/lib/spring-boot-starter-security-2.0.2.RELEASE.jar 366299 Tue May 08 08:06:20 CEST 2018 BOOT-INF/lib/spring-aop-5.0.6.RELEASE.jar 691611 Tue May 08 15:25:12 CEST 2018 BOOT-INF/lib/spring-security-config-5.0.5.RELEASE.jar 494788 Tue May 08 15:24:48 CEST 2018 BOOT-INF/lib/spring-security-web-5.0.5.RELEASE.jar 72603 Thu Jan 10 22:41:24 CET 2019 BOOT-INF/lib/spring-security-crypto-5.1.3.RELEASE.jar 433210 Thu Jan 10 22:41:26 CET 2019 BOOT-INF/lib/spring-security-core-5.1.3.RELEASE.jar 660573 Tue May 08 08:06:02 CEST 2018 BOOT-INF/lib/spring-beans-5.0.6.RELEASE.jar 1090735 Tue May 08 08:06:32 CEST 2018 BOOT-INF/lib/spring-context-5.0.6.RELEASE.jar 1226584 Tue May 08 08:05:54 CEST 2018 BOOT-INF/lib/spring-core-5.0.6.RELEASE.jar 21704 Tue May 08 08:05:42 CEST 2018 BOOT-INF/lib/spring-jcl-5.0.6.RELEASE.jar 279878 Tue May 08 08:06:20 CEST 2018 BOOT-INF/lib/spring-expression-5.0.6.RELEASE.jar 13769 Tue Nov 13 13:35:54 CET 2018 BOOT-INF/lib/kotlin-stdlib-jdk8-1.3.10.jar 1181292 Tue Nov 13 13:25:52 CET 2018 BOOT-INF/lib/kotlin-stdlib-1.3.10.jar 151024 Tue Nov 13 13:24:28 CET 2018 BOOT-INF/lib/kotlin-stdlib-common-1.3.10.jar 17536 Tue Dec 17 16:10:34 CET 2013 BOOT-INF/lib/annotations-13.0.jar 3137 Tue Nov 13 13:35:52 CET 2018 BOOT-INF/lib/kotlin-stdlib-jdk7-1.3.10.jar 2645740 Tue Nov 13 13:33:06 CET 2018 BOOT-INF/lib/kotlin-reflect-1.3.10.jar 501860 Wed Aug 15 21:36:52 CEST 2018 BOOT-INF/lib/commons-lang3-3.8.jar 127509 Fri Aug 04 15:17:50 CEST 2017 BOOT-INF/lib/javax.ws.rs-api-2.1.jar 164361 Sun Dec 23 12:30:54 CET 2018 BOOT-INF/lib/klaxon-5.0.1.jar 50732 Thu Jan 03 15:45:18 CET 2019 BOOT-INF/lib/java-jwt-3.5.0.jar 1342410 Mon Mar 26 15:13:56 CEST 2018 BOOT-INF/lib/jackson-databind-2.9.5.jar 66519 Sat Jul 29 20:53:26 CEST 2017 BOOT-INF/lib/jackson-annotations-2.9.0.jar 321590 Mon Mar 26 08:04:00 CEST 2018 BOOT-INF/lib/jackson-core-2.9.5.jar 335042 Tue Oct 17 08:53:20 CEST 2017 BOOT-INF/lib/commons-codec-1.11.jar 1007502 Tue Aug 07 08:59:10 CEST 2018 BOOT-INF/lib/mysql-connector-java-5.1.47.jar
I finally solved the problem. I don't if know using the BufferedReader is still the best practice, but I decided to keep it in my code as everything was done with it already. So I dropped the use of File class, and I used the following to get a resource from src/main/resources: var line: String? val bufferedReader = BufferedReader(InputStreamReader(Thread.currentThread().contextClassLoader.getResourceAsStream(csvLocation))) do { line = bufferedReader.readLine() if (line != null) { //Do something with 'line' } } while (line != null) csvLocation value is "data/myFile.csv". This file is located in src/main/resources/data Finally this solution works in my IDE and in the generated jar. Problem solved.
The production app will not run in your IDE, right? So that is of lesser importance than finding where the file exists on the classpath. Essentially, there is no src/main/resources dir in the jar file - that directory is just a Maven convention for holding resources in a project. If you crack the jar and find the files in question, you'll understand better where Maven puts those files at package time and how to access them. Also note, a Maven-aware IDE will put files in src/main/resources on the app classpath, so the app will likely run in the IDE as well once the correct solution is identified. To access the application.properties file in the example, use getResource or getResourceAsStream as suggested, with path /BOOT-INF/classes/application.properties. Note the first slash.
Listing missing months in an array of dates
I have a list of transactions in an array. => [Wed, 23 Oct 2013, Mon, 18 Nov 2013, Fri, 22 Nov 2013, Mon, 13 Jan 2014, Tue, 28 Jan 2014, Mon, 03 Feb 2014, Mon, 10 Feb 2014, Tue, 18 Feb 2014, Fri, 07 Mar 2014, Mon, 31 Mar 2014, Mon, 07 Apr 2014, Tue, 10 Jun 2014, Mon, 30 Jun 2014, Mon, 22 Sep 2014, Mon, 06 Oct 2014, Fri, 14 Nov 2014, Tue, 18 Nov 2014, Fri, 26 Dec 2014, Thu, 15 Jan 2015, Mon, 23 Mar 2015, Mon, 20 Apr 2015] I need to compare the dates of each transaction and list any months that are missing in the list of months and year. Here is what I have now... #find_transactions = (#user.transactions.find_all { |t| (t.name 'name' }) #trans_dates = #find_transactions.map(&:date).sort!.map { |s| Date.strptime(s, '%Y-%m') }.each_cons(2).map{ |d1,d2| d1.next_month == d2 } This method currently gives me a true or false if each month is there but I need to actually have the method print a list of months that are missing. I would like to have it print the month and year together. Here is the response this method gives me... => [true, false, true, false, false, true, false, true, false, false, false, true, true] I want a response like this... => [March 2015, December 2014, September 2014] Thanks in advance!
Edit: For array already being composed of date objects you can do: require 'date' dates = [Wed, 23 Oct 2013, Mon, 18 Nov 2013, Fri, 22 Nov 2013, Mon, 13 Jan 2014, Tue, 28 Jan 2014, Mon, 03 Feb 2014, Mon, 10 Feb 2014, Tue, 18 Feb 2014, Fri, 07 Mar 2014, Mon, 31 Mar 2014, Mon, 07 Apr 2014, Tue, 10 Jun 2014, Mon, 30 Jun 2014, Mon, 22 Sep 2014, Mon, 06 Oct 2014, Fri, 14 Nov 2014, Tue, 18 Nov 2014, Fri, 26 Dec 2014, Thu, 15 Jan 2015, Mon, 23 Mar 2015, Mon, 20 Apr 2015] all_dates = [] dates.first.upto(dates.last) {|x| all_dates << x.strftime('%b %Y') if x.day == 1 || x == dates.first} d = dates.map {|x| x.strftime('%b %Y')}.uniq p (all_dates - d) #=> ["Dec 2013", "May 2014", "Jul 2014", "Aug 2014", "Feb 2015"] Edit: Below methods are for an array of date strings You can try this: require 'date' dates = ["Wed, 23 Oct 2013", "Mon, 18 Nov 2013", "Fri, 22 Nov 2013", "Mon, 13 Jan 2014", "Tue, 28 Jan 2014", "Mon, 03 Feb 2014", "Mon, 10 Feb 2014", "Tue, 18 Feb 2014", "Fri, 07 Mar 2014", "Mon, 31 Mar 2014", "Mon, 07 Apr 2014", "Tue, 10 Jun 2014", "Mon, 30 Jun 2014", "Mon, 22 Sep 2014", "Mon, 06 Oct 2014", "Fri, 14 Nov 2014", "Tue, 18 Nov 2014", "Fri, 26 Dec 2014", "Thu, 15 Jan 2015", "Mon, 23 Mar 2015", "Mon, 20 Apr 2015"] all_dates = [] d = dates.map {|x| Date.parse(x[8..-1])}.uniq counter = d.first until counter == d.last all_dates << counter counter = counter.next_month end p (all_dates - d).map {|x| x.strftime('%b %Y')} #=> ["Dec 2013", "May 2014", "Jul 2014", "Aug 2014", "Feb 2015"] Another (more concise) way would be: require 'date' dates = ["Wed, 23 Oct 2013", "Mon, 18 Nov 2013", "Fri, 22 Nov 2013", "Mon, 13 Jan 2014", "Tue, 28 Jan 2014", "Mon, 03 Feb 2014", "Mon, 10 Feb 2014", "Tue, 18 Feb 2014", "Fri, 07 Mar 2014", "Mon, 31 Mar 2014", "Mon, 07 Apr 2014", "Tue, 10 Jun 2014", "Mon, 30 Jun 2014", "Mon, 22 Sep 2014", "Mon, 06 Oct 2014", "Fri, 14 Nov 2014", "Tue, 18 Nov 2014", "Fri, 26 Dec 2014", "Thu, 15 Jan 2015", "Mon, 23 Mar 2015", "Mon, 20 Apr 2015"] all_dates = [] d = dates.map {|x| Date.parse(x[8..-1])}.uniq d.first.upto(d.last) {|x| all_dates << x if x.day == 1} p (all_dates - d).map {|x| x.strftime('%b %Y')} #=> ["Dec 2013", "May 2014", "Jul 2014", "Aug 2014", "Feb 2015"]
This is one way you could do that. Code require 'date' def missing_months(dates) a = dates.map { |s| d = Date.strptime(s, '%a, %d %b %Y'); d - d.day + 1 } (all_months_in_range(*a.minmax) -a).map { |d| d.strftime('%b %Y') } end def all_months_in_range(f,l) (12*(l.year-f.year)+l.month-f.month+1).times.map do |i| y,m = (f.month+i).divmod(12) y += f.year (m=12; y-=1) if m ==0 Date.new(y,m) end end Example dates = ['Wed, 23 Oct 2013', 'Mon, 18 Nov 2013', 'Fri, 22 Nov 2013', 'Fri, 14 Nov 2014', 'Tue, 18 Nov 2014', 'Fri, 26 Dec 2014', 'Mon, 13 Jan 2014', 'Tue, 28 Jan 2014', 'Mon, 03 Feb 2014', 'Mon, 31 Mar 2014', 'Mon, 07 Apr 2014', 'Tue, 10 Jun 2014', 'Mon, 30 Jun 2014', 'Mon, 22 Sep 2014', 'Mon, 06 Oct 2014', 'Mon, 10 Feb 2014', 'Tue, 18 Feb 2014', 'Fri, 07 Mar 2014', 'Thu, 15 Jan 2015', 'Mon, 23 Mar 2015', 'Mon, 20 Apr 2015'] missing_months(dates) #=> ["Dec 2013", "May 2014", "Jul 2014", "Aug 2014", "Feb 2015"] Notice that the dates needn't be sorted. Explanation For the example above: a = dates.map { |s| d = Date.strptime(s, '%a, %d %b %Y'); d - d.day + 1 } #=> [#<Date: 2013-10-01 ((2456567j,0s,0n),+0s,2299161j)>, # #<Date: 2013-11-01 ((2456598j,0s,0n),+0s,2299161j)>, # ... # #<Date: 2015-04-01 ((2457114j,0s,0n),+0s,2299161j)>] Notice that each of these dates is on the first of the month. Next, obtain the first and last of these dates: f,l = a.minmax f #=> [#<Date: 2013-10-01 ((2456567j,0s,0n),+0s,2299161j)>, l #=> #<Date: 2015-04-01 ((2457114j,0s,0n),+0s,2299161j)>] Now pass f and l to all_months_in_range to create an array that contains a date object for the first day of each month between f and l. b = all_months_in_range(f,l) #=> [#<Date: 2013-10-01 ((2456567j,0s,0n),+0s,2299161j)>, # #<Date: 2013-11-01 ((2456598j,0s,0n),+0s,2299161j)>, # ... # #<Date: 2015-04-01 ((2457114j,0s,0n),+0s,2299161j)>] b.size #=> 19 I will skip an explanation of this helper method, as it is quite straightforward. Compute that difference between arrays b and a to obtain the missing beginning-of-month dates: c = b-a #=> [#<Date: 2013-12-01 ((2456628j,0s,0n),+0s,2299161j)>, # #<Date: 2014-05-01 ((2456779j,0s,0n),+0s,2299161j)>, # #<Date: 2014-07-01 ((2456840j,0s,0n),+0s,2299161j)>, # #<Date: 2014-08-01 ((2456871j,0s,0n),+0s,2299161j)>, # #<Date: 2015-02-01 ((2457055j,0s,0n),+0s,2299161j)>] Lastly, convert these dates to the desired format: c.map { |d| d.strftime('%b %Y') } #=> ["Dec 2013", "May 2014", "Jul 2014", "Aug 2014", "Feb 2015"] Addendum: after reading #Sid's answer, I see I could have saved myself some trouble in my helper method by using Date#next_month: def all_months_in_range(f,l) (12*(l.year-f.year)+l.month-f.month+1).times.map { |i| f.next_month(i) } end
This isn't very elegant, but it worked. I started with your original code, #SupremeA, and built off of that. require 'date' dates = ['Wed, 23 Oct 2013', 'Mon, 18 Nov 2013', 'Fri, 22 Nov 2013', 'Mon, 13 Jan 2014', 'Tue, 28 Jan 2014', 'Mon, 03 Feb 2014', 'Mon, 10 Feb 2014', 'Tue, 18 Feb 2014', 'Fri, 07 Mar 2014', 'Mon, 31 Mar 2014', 'Mon, 07 Apr 2014', 'Tue, 10 Jun 2014', 'Mon, 30 Jun 2014', 'Mon, 22 Sep 2014', 'Mon, 06 Oct 2014', 'Fri, 14 Nov 2014', 'Tue, 18 Nov 2014', 'Fri, 26 Dec 2014', 'Thu, 15 Jan 2015', 'Mon, 23 Mar 2015', 'Mon, 20 Apr 2015'] new_dates = [] dates.each { |d| new_dates.push(Date.parse(d).strftime('%B %Y')) } sorted_dates = new_dates.map { |s| Date.strptime(s, '%B %Y') }.sort.uniq missing_months = [] sorted_dates.each_cons(2) do |d1,d2| d = d1 while d.next_month != d2 missing_months.push(d.next_month.strftime('%B %Y')) d = d >> 1 end end p missing_months => ["December 2013", "May 2014", "July 2014", "August 2014", "February 2015"]
How sort this hash of hashes
I am struggling to sort this hash listed below: { 17=>{:id=>17, :count=>1, :created_at=>Wed, 05 Sep 2012 19:02:34 UTC +00:00}, 14=>{:id=>14, :count=>2, :created_at=>Sun, 02 Sep 2012 19:20:28 UTC +00:00}, 9=>{:id=>9, :count=>0, :created_at=>Sun, 02 Sep 2012 17:09:35 UTC +00:00}, 10=>{:id=>10, :count=>2, :created_at=>Sat, 01 Sep 2012 17:09:56 UTC +00:00}, 11=>{:id=>11, :count=>0, :created_at=>Fri, 31 Aug 2012 19:13:57 UTC +00:00}, 12=>{:id=>12, :count=>2, :created_at=>Thu, 30 Aug 2012 19:19:32 UTC +00:00}, 13=>{:id=>13, :count=>0, :created_at=>Thu, 23 Aug 2012 19:20:09 UTC +00:00} } The above hash should be sorted on count and created_of and look like this hash: { 12=>{:id=>12, :count=>2, :created_at=>Thu, 30 Aug 2012 19:19:32 UTC +00:00}, 10=>{:id=>10, :count=>2, :created_at=>Sat, 01 Sep 2012 17:09:56 UTC +00:00}, 14=>{:id=>14, :count=>2, :created_at=>Sun, 02 Sep 2012 19:20:28 UTC +00:00}, 17=>{:id=>17, :count=>1, :created_at=>Wed, 05 Sep 2012 19:02:34 UTC +00:00}, 13=>{:id=>13, :count=>0, :created_at=>Thu, 23 Aug 2012 19:20:09 UTC +00:00}, 11=>{:id=>11, :count=>0, :created_at=>Fri, 31 Aug 2012 19:13:57 UTC +00:00}, 9=>{:id=>9, :count=>0, :created_at=>Sun, 02 Sep 2012 17:09:35 UTC +00:00} }
Assuming you are using Ruby 1.9 where hashes have order: Hash[data.sort_by { |key, h| [-h[:count], h[:created_at]] }]
In Ruby 1.8, you cannot sort a hash as a hash has no order. In Ruby 1.9, a hash iteration order is defined by the insertion order. You therefore have to create a new hash in which you will insert the elements in the right order. sorted_keys = hash.keys.sort sorted_hash = Hash.new sorted_keys.each do |k| sorted_hash[k] = hash[k] end
How do you get DateTime.parse to return a time in your time zone?
I need this require 'date' DateTime.parse "Mon, Dec 27 6:30pm" to return a DateTime for 6:30pm in the EDT timezone, but it returns one in UTC. How can I get a EST DateTime or convert the UTC one into an EDT DateTime with a 6:30pm value?
OK I'm going to offer an answer to my own question require 'time' ENV["TZ"] = "US/Eastern" Time.parse("Mon, Dec 27 6:30pm").to_datetime => #<DateTime: 2011-12-27T18:30:00-05:00 (117884327/48,-5/24,2299161)>
In Rails, this worked nicely for me DateTime.parse "Mon, Dec 27 6:30pm #{Time.zone}" It won't work in vanilla Ruby though.
Final answer ;-) require 'date' estHoursOffset = -5 estOffset = Rational(estHoursOffset, 24) date = (DateTime.parse("Mon, Dec 27 6:30pm") - (estHoursOffset/24.0)).new_offset(estOffset) (or -4 for EDT)
DateTime#change() You can try using change() after parsing it to alter the timezone offset: DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-0400' ) # => Wed, 27 Dec 2017 18:30:00 -0400 You can also just use the hours: DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4' ) # => Wed, 27 Dec 2017 18:30:00 -0400 But, be careful, you cannot use an integer: DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: -4 ) # => Wed, 27 Dec 2017 18:30:00 +0000 If you need to determine the correct offset to use based on a time zone you can do something like this: offset = ( Time.zone_offset('EDT') / 1.hour ).to_s # => "-4" DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: offset ) # => Wed, 27 Dec 2017 18:30:00 -0400 You can also use change() to manually set other parts of the DateTime as well, like setting the hour to noon: DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4', hour: 12 ) # => Wed, 27 Dec 2017 12:00:00 -0400 Be careful with that one because you can see that it's cleared the minutes as well. Here's the docs for the change() method: http://api.rubyonrails.org/v5.1/classes/DateTime.html#method-i-change
If you're using Rails' ActiveSupport: "Mon, Dec 27 6:30pm".in_time_zone(-4.hours).to_datetime # => Mon, 27 Dec 2021 18:30:00 -0400 Time.find_zone(-4.hours).parse("Mon, Dec 27 6:30pm").to_datetime # => Mon, 27 Dec 2021 18:30:00 -0400 If you want to use the local daylight saving time (DST) rules, you could use: "Mon, Dec 27 6:30pm".in_time_zone("Eastern Time (US & Canada)") # => Mon, 27 Dec 2021 18:30:00 EST -05:00 Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm") # => Mon, 27 Dec 2021 18:30:00 EST -05:00 Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm").to_datetime # => Mon, 27 Dec 2021 18:30:00 -0500 Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm") # => Sun, 27 Jun 2021 18:30:00 EDT -04:00 Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm").to_datetime # => Sun, 27 Jun 2021 18:30:00 -0400 Time.find_zone("EST5EDT").parse("Mon, Jun 27 6:30pm").to_datetime # => Sun, 27 Jun 2021 18:30:00 -0400 Notice the date in June, above, is automatically set to EDT (-0400) because this date is in DST, contrary to the December date. To force EST regardless if date is within DST or not: Time.find_zone("EST").parse("Mon, Jun 27 6:30pm") # => Sun, 27 Jun 2021 18:30:00 EST -05:00 Time.find_zone("EST").parse("Mon, Jun 27 6:30pm").to_datetime # => Sun, 27 Jun 2021 18:30:00 -0500